| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| example.js | 100% | (83 / 83) | 100% | (73 / 73) | 100% | (12 / 12) | 100% | (83 / 83) | |
| lib.npmtest_cca.js | 100% | (16 / 16) | 100% | (14 / 14) | 100% | (3 / 3) | 100% | (16 / 16) | |
| test.js | 100% | (54 / 54) | 100% | (39 / 39) | 100% | (13 / 13) | 100% | (54 / 54) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | 2 2 2 2 2 2 2 1 2 2 2 2 1 2 2 2 2 2 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1 1 2 2 3 3 3 3 1 3 3 3 1 3 1 1 1 1 1 1 1 1 1 1 1 1 6 6 1 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /*
example.js
quickstart example
instruction
1. save this script as example.js
2. run the shell command:
$ npm install npmtest-cca && PORT=8081 node example.js
3. play with the browser-demo on http://127.0.0.1:8081
*/
/* istanbul instrument in package npmtest_cca */
/*jslint
bitwise: true,
browser: true,
maxerr: 8,
maxlen: 96,
node: true,
nomen: true,
regexp: true,
stupid: true
*/
(function () {
'use strict';
var local;
// run shared js-env code - pre-init
(function () {
// init local
local = {};
// init modeJs
local.modeJs = (function () {
try {
return typeof navigator.userAgent === 'string' &&
typeof document.querySelector('body') === 'object' &&
typeof XMLHttpRequest.prototype.open === 'function' &&
'browser';
} catch (errorCaughtBrowser) {
return module.exports &&
typeof process.versions.node === 'string' &&
typeof require('http').createServer === 'function' &&
'node';
}
}());
// init global
local.global = local.modeJs === 'browser'
? window
: global;
// init utility2_rollup
local = local.global.utility2_rollup || (local.modeJs === 'browser'
? local.global.utility2_npmtest_cca
: global.utility2_moduleExports);
// export local
local.global.local = local;
}());
switch (local.modeJs) {
// post-init
// run browser js-env code - post-init
/* istanbul ignore next */
case 'browser':
local.testRunBrowser = function (event) {
Eif (!event || (event &&
event.currentTarget &&
event.currentTarget.className &&
event.currentTarget.className.includes &&
event.currentTarget.className.includes('onreset'))) {
// reset output
Array.from(
document.querySelectorAll('body > .resettable')
).forEach(function (element) {
switch (element.tagName) {
case 'INPUT':
case 'TEXTAREA':
element.value = '';
break;
default:
element.textContent = '';
}
});
}
switch (event && event.currentTarget && event.currentTarget.id) {
case 'testRunButton1':
// show tests
Eif (document.querySelector('#testReportDiv1').style.display === 'none') {
document.querySelector('#testReportDiv1').style.display = 'block';
document.querySelector('#testRunButton1').textContent =
'hide internal test';
local.modeTest = true;
local.testRunDefault(local);
// hide tests
} else {
document.querySelector('#testReportDiv1').style.display = 'none';
document.querySelector('#testRunButton1').textContent = 'run internal test';
}
break;
// custom-case
default:
break;
}
Iif (document.querySelector('#inputTextareaEval1') && (!event || (event &&
event.currentTarget &&
event.currentTarget.className &&
event.currentTarget.className.includes &&
event.currentTarget.className.includes('oneval')))) {
// try to eval input-code
try {
/*jslint evil: true*/
eval(document.querySelector('#inputTextareaEval1').value);
} catch (errorCaught) {
console.error(errorCaught);
}
}
};
// log stderr and stdout to #outputTextareaStdout1
['error', 'log'].forEach(function (key) {
console[key + '_original'] = console[key];
console[key] = function () {
var element;
console[key + '_original'].apply(console, arguments);
element = document.querySelector('#outputTextareaStdout1');
Iif (!element) {
return;
}
// append text to #outputTextareaStdout1
element.value += Array.from(arguments).map(function (arg) {
return typeof arg === 'string'
? arg
: JSON.stringify(arg, null, 4);
}).join(' ') + '\n';
// scroll textarea to bottom
element.scrollTop = element.scrollHeight;
};
});
// init event-handling
['change', 'click', 'keyup'].forEach(function (event) {
Array.from(document.querySelectorAll('.on' + event)).forEach(function (element) {
element.addEventListener(event, local.testRunBrowser);
});
});
// run tests
local.testRunBrowser();
break;
// run node js-env code - post-init
/* istanbul ignore next */
case 'node':
// export local
module.exports = local;
// require modules
local.fs = require('fs');
local.http = require('http');
local.url = require('url');
// init assets
local.assetsDict = local.assetsDict || {};
/* jslint-ignore-begin */
local.assetsDict['/assets.index.template.html'] = '\
<!doctype html>\n\
<html lang="en">\n\
<head>\n\
<meta charset="UTF-8">\n\
<meta name="viewport" content="width=device-width, initial-scale=1">\n\
<title>{{env.npm_package_name}} (v{{env.npm_package_version}})</title>\n\
<style>\n\
/*csslint\n\
box-sizing: false,\n\
universal-selector: false\n\
*/\n\
* {\n\
box-sizing: border-box;\n\
}\n\
body {\n\
background: #dde;\n\
font-family: Arial, Helvetica, sans-serif;\n\
margin: 2rem;\n\
}\n\
body > * {\n\
margin-bottom: 1rem;\n\
}\n\
.utility2FooterDiv {\n\
margin-top: 20px;\n\
text-align: center;\n\
}\n\
</style>\n\
<style>\n\
/*csslint\n\
*/\n\
textarea {\n\
font-family: monospace;\n\
height: 10rem;\n\
width: 100%;\n\
}\n\
textarea[readonly] {\n\
background: #ddd;\n\
}\n\
</style>\n\
</head>\n\
<body>\n\
<!-- utility2-comment\n\
<div id="ajaxProgressDiv1" style="background: #d00; height: 2px; left: 0; margin: 0; padding: 0; position: fixed; top: 0; transition: background 0.5s, width 1.5s; width: 25%;"></div>\n\
utility2-comment -->\n\
<h1>\n\
<!-- utility2-comment\n\
<a\n\
{{#if env.npm_package_homepage}}\n\
href="{{env.npm_package_homepage}}"\n\
{{/if env.npm_package_homepage}}\n\
target="_blank"\n\
>\n\
utility2-comment -->\n\
{{env.npm_package_name}} (v{{env.npm_package_version}})\n\
<!-- utility2-comment\n\
</a>\n\
utility2-comment -->\n\
</h1>\n\
<h3>{{env.npm_package_description}}</h3>\n\
<!-- utility2-comment\n\
<h4><a download href="assets.app.js">download standalone app</a></h4>\n\
<button class="onclick onreset" id="testRunButton1">run internal test</button><br>\n\
<div id="testReportDiv1" style="display: none;"></div>\n\
utility2-comment -->\n\
\n\
\n\
\n\
<label>stderr and stdout</label>\n\
<textarea class="resettable" id="outputTextareaStdout1" readonly></textarea>\n\
<!-- utility2-comment\n\
{{#if isRollup}}\n\
<script src="assets.app.js"></script>\n\
{{#unless isRollup}}\n\
utility2-comment -->\n\
<script src="assets.utility2.rollup.js"></script>\n\
<script src="jsonp.utility2._stateInit?callback=window.utility2._stateInit"></script>\n\
<script src="assets.npmtest_cca.rollup.js"></script>\n\
<script src="assets.example.js"></script>\n\
<script src="assets.test.js"></script>\n\
<!-- utility2-comment\n\
{{/if isRollup}}\n\
utility2-comment -->\n\
<div class="utility2FooterDiv">\n\
[ this app was created with\n\
<a href="https://github.com/kaizhu256/node-utility2" target="_blank">utility2</a>\n\
]\n\
</div>\n\
</body>\n\
</html>\n\
';
/* jslint-ignore-end */
Iif (local.templateRender) {
local.assetsDict['/'] = local.templateRender(
local.assetsDict['/assets.index.template.html'],
{
env: local.objectSetDefault(local.env, {
npm_package_description: 'the greatest app in the world!',
npm_package_name: 'my-app',
npm_package_nameAlias: 'my_app',
npm_package_version: '0.0.1'
})
}
);
} else {
local.assetsDict['/'] = local.assetsDict['/assets.index.template.html']
.replace((/\{\{env\.(\w+?)\}\}/g), function (match0, match1) {
// jslint-hack
String(match0);
switch (match1) {
case 'npm_package_description':
return 'the greatest app in the world!';
case 'npm_package_name':
return 'my-app';
case 'npm_package_nameAlias':
return 'my_app';
case 'npm_package_version':
return '0.0.1';
}
});
}
// run the cli
Eif (local.global.utility2_rollup || module !== require.main) {
break;
}
local.assetsDict['/assets.example.js'] =
local.assetsDict['/assets.example.js'] ||
local.fs.readFileSync(__filename, 'utf8');
local.assetsDict['/assets.npmtest_cca.rollup.js'] =
local.assetsDict['/assets.npmtest_cca.rollup.js'] ||
local.fs.readFileSync(
// buildCustomOrg-hack
local.npmtest_cca.__dirname +
'/lib.npmtest_cca.js',
'utf8'
).replace((/^#!/), '//');
local.assetsDict['/favicon.ico'] = local.assetsDict['/favicon.ico'] || '';
// if $npm_config_timeout_exit exists,
// then exit this process after $npm_config_timeout_exit ms
if (Number(process.env.npm_config_timeout_exit)) {
setTimeout(process.exit, Number(process.env.npm_config_timeout_exit));
}
// start server
if (local.global.utility2_serverHttp1) {
break;
}
process.env.PORT = process.env.PORT || '8081';
console.error('server starting on port ' + process.env.PORT);
local.http.createServer(function (request, response) {
request.urlParsed = local.url.parse(request.url);
if (local.assetsDict[request.urlParsed.pathname] !== undefined) {
response.end(local.assetsDict[request.urlParsed.pathname]);
return;
}
response.statusCode = 404;
response.end();
}).listen(process.env.PORT);
break;
}
}());
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 2 2 2 2 2 2 2 1 2 2 2 2 1 1 1 1 | /* istanbul instrument in package npmtest_cca */
/*jslint
bitwise: true,
browser: true,
maxerr: 8,
maxlen: 96,
node: true,
nomen: true,
regexp: true,
stupid: true
*/
(function () {
'use strict';
var local;
// run shared js-env code - pre-init
(function () {
// init local
local = {};
// init modeJs
local.modeJs = (function () {
try {
return typeof navigator.userAgent === 'string' &&
typeof document.querySelector('body') === 'object' &&
typeof XMLHttpRequest.prototype.open === 'function' &&
'browser';
} catch (errorCaughtBrowser) {
return module.exports &&
typeof process.versions.node === 'string' &&
typeof require('http').createServer === 'function' &&
'node';
}
}());
// init global
local.global = local.modeJs === 'browser'
? window
: global;
// init utility2_rollup
local = local.global.utility2_rollup || local;
// init lib
local.local = local.npmtest_cca = local;
// init exports
if (local.modeJs === 'browser') {
local.global.utility2_npmtest_cca = local;
} else {
module.exports = local;
module.exports.__dirname = __dirname;
module.exports.module = module;
}
}());
}());
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | 2 2 2 2 2 2 2 1 2 2 1 1 1 1 2 2 2 2 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 1 2 2 1 2 2 1 1 1 1 1 | /* istanbul instrument in package npmtest_cca */
/*jslint
bitwise: true,
browser: true,
maxerr: 8,
maxlen: 96,
node: true,
nomen: true,
regexp: true,
stupid: true
*/
(function () {
'use strict';
var local;
// run shared js-env code - pre-init
(function () {
// init local
local = {};
// init modeJs
local.modeJs = (function () {
try {
return typeof navigator.userAgent === 'string' &&
typeof document.querySelector('body') === 'object' &&
typeof XMLHttpRequest.prototype.open === 'function' &&
'browser';
} catch (errorCaughtBrowser) {
return module.exports &&
typeof process.versions.node === 'string' &&
typeof require('http').createServer === 'function' &&
'node';
}
}());
// init global
local.global = local.modeJs === 'browser'
? window
: global;
switch (local.modeJs) {
// re-init local from window.local
case 'browser':
local = local.global.utility2.objectSetDefault(
local.global.utility2_rollup || local.global.local,
local.global.utility2
);
break;
// re-init local from example.js
case 'node':
local = (local.global.utility2_rollup || require('utility2'))
.requireExampleJsFromReadme();
break;
}
// export local
local.global.local = local;
}());
// run shared js-env code - function
(function () {
return;
}());
switch (local.modeJs) {
// run browser js-env code - function
case 'browser':
break;
// run node js-env code - function
case 'node':
break;
}
// run shared js-env code - post-init
(function () {
return;
}());
switch (local.modeJs) {
// run browser js-env code - post-init
case 'browser':
local.testCase_browser_nullCase = local.testCase_browser_nullCase || function (
options,
onError
) {
/*
* this function will test browsers's null-case handling-behavior-behavior
*/
onError(null, options);
};
// run tests
local.nop(local.modeTest &&
document.querySelector('#testRunButton1') &&
document.querySelector('#testRunButton1').click());
break;
// run node js-env code - post-init
/* istanbul ignore next */
case 'node':
local.testCase_buildApidoc_default = local.testCase_buildApidoc_default || function (
options,
onError
) {
/*
* this function will test buildApidoc's default handling-behavior-behavior
*/
options = { modulePathList: module.paths };
local.buildApidoc(options, onError);
};
local.testCase_buildApp_default = local.testCase_buildApp_default || function (
options,
onError
) {
/*
* this function will test buildApp's default handling-behavior-behavior
*/
local.testCase_buildReadme_default(options, local.onErrorThrow);
local.testCase_buildLib_default(options, local.onErrorThrow);
local.testCase_buildTest_default(options, local.onErrorThrow);
local.testCase_buildCustomOrg_default(options, local.onErrorThrow);
options = [];
local.buildApp(options, onError);
};
local.testCase_buildCustomOrg_default = local.testCase_buildCustomOrg_default ||
function (options, onError) {
/*
* this function will test buildCustomOrg's default handling-behavior
*/
options = {};
local.buildCustomOrg(options, onError);
};
local.testCase_buildLib_default = local.testCase_buildLib_default || function (
options,
onError
) {
/*
* this function will test buildLib's default handling-behavior
*/
options = {};
local.buildLib(options, onError);
};
local.testCase_buildReadme_default = local.testCase_buildReadme_default || function (
options,
onError
) {
/*
* this function will test buildReadme's default handling-behavior-behavior
*/
options = {};
local.buildReadme(options, onError);
};
local.testCase_buildTest_default = local.testCase_buildTest_default || function (
options,
onError
) {
/*
* this function will test buildTest's default handling-behavior
*/
options = {};
local.buildTest(options, onError);
};
local.testCase_webpage_default = local.testCase_webpage_default || function (
options,
onError
) {
/*
* this function will test webpage's default handling-behavior
*/
options = { modeCoverageMerge: true, url: local.serverLocalHost + '?modeTest=1' };
local.browserTest(options, onError);
};
// run test-server
local.testRunServer(local);
break;
}
}());
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| main.js | 100% | (4 / 4) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (4 / 4) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
exports.analyseManifest = require('./src/analyse-manifest');
exports.parseAndMergeManifests = require('./src/parse-and-merge-manifests');
exports.updateConfigXml = require('./src/update-config-xml');
exports.pluginMaps = require('./src/plugin-maps');
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| analyse-manifest.js | 12.66% | (10 / 79) | 0% | (0 / 39) | 0% | (0 / 12) | 12.66% | (10 / 79) | |
| parse-and-merge-manifests.js | 5.26% | (1 / 19) | 0% | (0 / 4) | 0% | (0 / 6) | 5.26% | (1 / 19) | |
| plugin-maps.js | 100% | (10 / 10) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (10 / 10) | |
| update-config-xml.js | 11.11% | (14 / 126) | 0% | (0 / 87) | 0% | (0 / 16) | 11.11% | (14 / 126) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | 1 1 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var pluginMaps = require('./plugin-maps');
var DEFAULT_PLUGINS = pluginMaps.DEFAULT_PLUGINS;
var PLUGIN_MAP = pluginMaps.PLUGIN_MAP;
var STALE_PLUGINS = pluginMaps.STALE_PLUGINS;
var ENGINE_MAP = pluginMaps.ENGINE_MAP;
var SOCKETS_MAP = pluginMaps.SOCKETS_MAP;
function mapPermissionsToPlugins(knownPermissionsMap, requestedPermissionsList) {
// We have to create three lists:
// 1. Permissions your app has requested and we know about (install these plugins)
// 2. Permissions your app has requested and we do not know about (warn about these)
// 3. Permissions your app has not requested (uninstall these plugins)
var ret = {
toInstall: [],
toUninstall: [],
unknown: [],
};
var knownPermissionsList = Object.keys(knownPermissionsMap);
requestedPermissionsList = requestedPermissionsList.slice(); // deep copy so we can modify in-place
requestedPermissionsList.forEach(function(requestedPermission) {
// Is this permission known?
var idx = knownPermissionsList.indexOf(requestedPermission);
if (idx != -1) {
ret.toInstall = ret.toInstall.concat(knownPermissionsMap[requestedPermission]);
// Remove from the list of known permissions, so that at the end of this we have all known permissions that arent requested
knownPermissionsList.splice(idx,1);
} else {
ret.unknown.push(requestedPermission);
}
});
// Uninstall whatever is left, since it was not requested
knownPermissionsList.forEach(function(permission) {
ret.toUninstall = ret.toUninstall.concat(knownPermissionsMap[permission]);
});
// Final step, bit of a hack, remove duplicate plugins from toUninstall list that exist in toInstall
// e.g. syncFS depends on identity. So, even if identity isn't in your manifest, don't uninstall it if you have syncFS
// The way we handle this is to add identity to the list of plugins to install for the syncFS permission
// so, the last thing to do is subtract the plugins to install from the plugins to not install, since there can be overlap.
ret.toUninstall = ret.toUninstall.filter(function(plugin) {
return ret.toInstall.indexOf(plugin) == -1;
});
return ret;
}
module.exports = function analyseManifest(manifest, options) {
options = options || {};
var ret = {
appId: undefined,
whitelist: [],
permissions: [],
pluginsToBeInstalled: [],
pluginsToBeNotInstalled: [],
pluginsNotRecognized: [],
};
(manifest.permissions || []).forEach(function(permission) {
if (typeof permission === "object") {
ret.permissions = ret.permissions.concat(Object.keys(permission));
} else if (permission === "<all_urls>") {
ret.whitelist.push("*");
} else {
var matchPatternParts = /([^:]+:\/\/[^\/]+)(\/.*)$/.exec(permission);
if (matchPatternParts) {
// Disregard paths in host permissions: path is required, but
// <scheme>://<host>/<any path> should translate to <scheme>://<host>/*
ret.whitelist.push(matchPatternParts[1] + "/*");
} else {
ret.permissions.push(permission);
}
}
});
var pluginsForPermissions = mapPermissionsToPlugins(PLUGIN_MAP, ret.permissions);
var engineSpec = options.webview || manifest.webview || "crosswalk";
ret.engineName = engineSpec.replace(/@.*/, '');
ret.engineVer = engineSpec.slice(ret.engineName.length + 1);
var pluginsForEngines = mapPermissionsToPlugins(ENGINE_MAP, [ret.engineName]);
var pluginsForSockets = mapPermissionsToPlugins(SOCKETS_MAP, Object.keys(manifest.sockets || {}));
ret.pluginsToBeInstalled = [].concat.apply([], [
pluginsForPermissions.toInstall,
pluginsForEngines.toInstall,
pluginsForSockets.toInstall,
DEFAULT_PLUGINS
]);
ret.pluginsToBeNotInstalled = [].concat.apply([], [
pluginsForPermissions.toUninstall,
pluginsForEngines.toUninstall,
pluginsForSockets.toUninstall,
STALE_PLUGINS
]);
ret.pluginsNotRecognized = pluginsForPermissions.unknown.concat(pluginsForSockets.unknown);
// Special case for bluetooth, since it uses boolean flags and not just the existance of keys.
if (manifest.bluetooth && typeof manifest.bluetooth === 'object') {
ret.pluginsToBeInstalled.push('cordova-plugin-chrome-apps-bluetooth');
(manifest.bluetooth.low_energy ? ret.pluginsToBeInstalled : ret.pluginsToBeNotInstalled).push('cordova-plugin-chrome-apps-bluetoothlowenergy');
(manifest.bluetooth.socket ? ret.pluginsToBeInstalled : ret.pluginsToBeNotInstalled).push('cordova-plugin-chrome-apps-bluetoothsocket');
} else {
ret.pluginsToBeNotInstalled = ret.pluginsToBeNotInstalled.concat([
'cordova-plugin-chrome-apps-bluetoothlowenergy',
'cordova-plugin-chrome-apps-bluetoothsocket',
'cordova-plugin-chrome-apps-bluetooth'
]);
}
// This next filter seems needless, but it happens when we still want plugins installed for which there are missing permissions, e.g. chrome.storage
ret.pluginsToBeNotInstalled = ret.pluginsToBeNotInstalled.filter(function(plugin) {
return ret.pluginsToBeInstalled.indexOf(plugin) == -1;
});
// Take only unique values
ret.pluginsToBeInstalled = ret.pluginsToBeInstalled.sort().filter(function(value, index, self) {
return self.indexOf(value) === index;
});
ret.pluginsToBeNotInstalled = ret.pluginsToBeNotInstalled.sort().filter(function(value, index, self) {
return self.indexOf(value) === index;
});
ret.pluginsNotRecognized = ret.pluginsNotRecognized.sort().filter(function(value, index, self) {
return self.indexOf(value) === index;
});
// This should happen rarely
pluginsForEngines.unknown.forEach(function(unknownEngine) {
console.warn('Engine not supported by cca: ' + unknownEngine + ' (skipping)');
});
if (manifest.key) {
ret.appId = require('./chrome-app-key-to-id')(manifest.key);
} else {
ret.appId = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
}
return ret;
};
function createCspString(manifest, platform) {
// Allow apps to define their own CSP.
if (manifest.csp) {
return manifest.csp;
}
var defaultSrc = 'file: data: blob: chrome-extension: gopher:';
if (platform == 'ios') {
defaultSrc += ' gap:';
} else if (platform == 'android') {
// Required for TalkBack
defaultSrc += ' https://ssl.gstatic.com';
}
if (manifest.cspUnsafeEval) {
defaultSrc += " 'unsafe-eval'";
}
if (manifest.cspUnsafeInline) {
defaultSrc += " 'unsafe-inline'";
}
var ret = 'default-src ' + defaultSrc + ';';
ret += ' connect-src *; media-src *;';
if (!manifest.cspUnsafeInline) {
ret += ' style-src ' + defaultSrc + " 'unsafe-inline';";
}
return ret;
}
module.exports.createCspString = createCspString;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 1 | /** Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Returns a promise for the manifest contents. module.exports = exports = function parseAndMergeManifests(manifestPath, platform, readFileFunc, Q) { var manifestMobilePath = manifestPath.replace(/manifest.json$/, 'manifest.mobile.json'); var manifest, manifestMobile; return readFileFunc(manifestPath).then(function(manifestData) { try { // jshint evil:true manifest = eval('(' + manifestData + ')'); // jshint evil:false } catch (e) { console.error(e); throw new Error('Unable to parse manifest ' + manifestPath); } return readFileFunc(manifestMobilePath).then(function(manifestMobileData) { try { // jshint evil:true manifestMobile = eval('(' + manifestMobileData + ')'); // jshint evil:false } catch (e) { console.error(e); throw new Error('Unable to parse manifest ' + manifestPath); } }, function(err) { // Swallow any errors opening the mobile manifest, it's not required. }).then(function() { var extend = require('node.extend'); manifest = extend(true, manifest, manifestMobile); // true -> deep recursive merge of these objects // If you want a specific platform manifest, also merge in its platform specific settings if (platform && platform in manifest) { manifest = extend(true, manifest, manifest[platform]); } return manifest; }); }, function(err) { throw new Error('Unable to open manifest ' + manifestPath + ' for reading.'); }); }; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | 1 1 1 1 1 1 1 1 1 1 | /*
* NOTE!
* If you remove/rename a plugin from these lists, add the old value to the STALE_PLUGINS list at the end.
* That way, it will be automatically removed on prepare.
* */
var DEFAULT_PLUGINS = [
'cordova-plugin-background-app',
'cordova-plugin-file',
'cordova-plugin-inappbrowser',
'cordova-plugin-network-information',
'cordova-plugin-statusbar',
'cordova-plugin-whitelist@1.0.0',
'cordova-plugin-chrome-apps-common',
'cordova-plugin-chrome-apps-runtime',
'cordova-plugin-chrome-apps-storage',
'cordova-plugin-chrome-apps-navigation',
'cordova-plugin-chrome-apps-bootstrap',
'cordova-plugin-chrome-apps-i18n',
'cordova-plugin-customevent-polyfill',
'cordova-plugin-blob-constructor-polyfill',
'cordova-plugin-xhr-blob-polyfill',
];
var PLUGIN_MAP = {
'alarms': ['cordova-plugin-chrome-apps-alarms', 'cordova-plugin-chrome-apps-storage'],
'audioCapture': ['cordova-plugin-chrome-apps-audiocapture'],
'background': [],
'fileSystem': ['cordova-plugin-chrome-apps-filesystem'],
'fullscreen': [],
'gcm': ['cordova-plugin-chrome-apps-gcm', 'cordova-plugin-chrome-apps-storage'],
'geolocation': ['cordova-plugin-geolocation'],
'identity': ['cordova-plugin-chrome-apps-identity'],
'idle': ['cordova-plugin-chrome-apps-idle'],
'notifications': ['cordova-plugin-chrome-apps-notifications', 'cordova-plugin-chrome-apps-storage'],
'payments': ['cordova-plugin-google-payments'],
'power': ['cordova-plugin-chrome-apps-power'],
'proxy': ['cordova-plugin-chrome-apps-proxy'],
'pushMessaging': ['cordova-plugin-chrome-apps-pushmessaging', 'cordova-plugin-chrome-apps-identity'],
'socket': ['cordova-plugin-chrome-apps-socket', 'cordova-plugin-chrome-apps-system-network'],
'storage': ['cordova-plugin-chrome-apps-storage'],
'system.cpu': ['cordova-plugin-chrome-apps-system-cpu'],
'system.display': ['cordova-plugin-chrome-apps-system-display'],
'system.memory': ['cordova-plugin-chrome-apps-system-memory'],
'system.network': ['cordova-plugin-chrome-apps-system-network'],
'system.storage': ['cordova-plugin-chrome-apps-system-storage'],
'unlimitedStorage': [],
'videoCapture': ['cordova-plugin-chrome-apps-videocapture'],
'usbDevices': ['cordova-plugin-chrome-apps-usb'],
'usb': ['cordova-plugin-chrome-apps-usb'],
};
var STALE_PLUGINS = [
'com.google.payments',
'org.apache.cordova.engine.crosswalk',
'org.chromium.syncfilesystem',
'org.chromium.alarms',
'org.chromium.audiocapture',
'org.chromium.backgroundapp',
'org.chromium.bluetooth',
'org.chromium.bluetoothlowenergy',
'org.chromium.bluetoothsocket',
'org.chromium.bootstrap',
'org.chromium.common',
'org.chromium.filesystem',
'org.chromium.gcm',
'org.chromium.i18n',
'org.chromium.identity',
'org.chromium.idle',
'org.chromium.iossocketscommon',
'org.chromium.navigation',
'org.chromium.notifications',
'org.chromium.polyfill.blob_constructor',
'org.chromium.polyfill.customevent',
'org.chromium.polyfill.xhr_features',
'org.chromium.power',
'org.chromium.pushmessaging',
'org.chromium.runtime',
'org.chromium.socket',
'org.chromium.sockets.tcp',
'org.chromium.sockets.tcpserver',
'org.chromium.sockets.udp',
'org.chromium.storage',
'org.chromium.system.cpu',
'org.chromium.system.display',
'org.chromium.system.memory',
'org.chromium.system.network',
'org.chromium.system.storage',
'org.chromium.usb',
'org.chromium.videocapture',
'org.chromium.frameworks.googleopensource',
'org.chromium.frameworks.googleplus',
'org.crosswalk.engine'
];
var ENGINE_MAP = {
'crosswalk': ['cordova-plugin-crosswalk-webview'],
'system': []
};
var SOCKETS_MAP = {
'udp': ['cordova-plugin-chrome-apps-sockets-udp'],
'tcp': ['cordova-plugin-chrome-apps-sockets-tcp'],
'tcpServer': ['cordova-plugin-chrome-apps-sockets-tcpserver'],
};
exports.DEFAULT_PLUGINS = DEFAULT_PLUGINS;
exports.PLUGIN_MAP = PLUGIN_MAP;
exports.STALE_PLUGINS = STALE_PLUGINS;
exports.ENGINE_MAP = ENGINE_MAP;
exports.SOCKETS_MAP = SOCKETS_MAP;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /** Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ 'use strict'; // configXmlDom: parsed with DOMParser. module.exports = exports = function updateConfigXml(manifest, analyzedManifest, configXmlDom) { var widget = configXmlDom.lastChild; // firstChild is the <xml> delcaration. function $(name) { var ret = widget.getElementsByTagName(name); return ret && ret[0]; } function getOrCreateRootNode(name) { var ret = $(name); if (!ret) { ret = configXmlDom.createElement(name); widget.appendChild(ret); } return ret; } function getOrCreatePlatformNode(name) { var plats = widget.getElementsByTagName('platform'); for (var i = 0; i < plats.length; ++i) { if (plats[i].getAttribute('name') == name) { return plats[i]; } } var newNode = configXmlDom.createElement('platform'); newNode.setAttribute('name', name); widget.appendChild(newNode); return newNode; } function setOrDeleteAttribute(node, name, value) { if (value) { node.setAttribute(name, value); } else { node.removeAttribute(name); } } // Find a <preference name="name" value=...> tag // If multiple exist, return the last one, if none - undefined. function getPreference(name) { var prefs = widget.getElementsByTagName('preference'); var pref; for (var i = 0; i < prefs.length; i++) { if (prefs[i].getAttribute('name') == name) { pref = prefs[i]; } } return pref; } function setOrCreatePreference(name, value) { var pref = getPreference(name); if (!pref) { pref = configXmlDom.createElement('preference'); pref.setAttribute('name', name); widget.appendChild(pref); } pref.setAttribute('value', value); return pref; } function deletePreference(name) { var node = getPreference(name); if (node) { node.parentNode.removeChild(node); } } function deleteAllChildren(parentNode, nodeName) { nodeName = nodeName.toUpperCase(); for (var i = 0; i < parentNode.childNodes.length; ) { if (parentNode.childNodes[i].nodeName.toUpperCase() == nodeName) { parentNode.removeChild(parentNode.childNodes[i]); } else { i++; } } if (parentNode.childNodes.length === 0) { parentNode.parentNode.removeChild(parentNode); } } function createIconNode(parentNode, src, size) { var newNode = configXmlDom.createElement('icon'); newNode.setAttribute('src', src); if (size) { newNode.setAttribute('width', size); } parentNode.appendChild(newNode); } function findLargestNumericKey(obj) { var bestSize = '0'; for (var size in obj) { bestSize = +size > +bestSize ? size : bestSize; } return bestSize; } var ver = manifest.version || '0.0.1'; if (!/^\d+(\.\d+){0,3}$/.test(ver)) { throw new Error('Invalid version: "' + ver + '" Must contain at most 4 numbers separated by periods.'); } widget.setAttribute('id', manifest.packageId || 'com.your.company.HelloWorld'); if (manifest.android && manifest.android.packageId) { widget.setAttribute('android-packageName', manifest.android.packageId); } if (manifest.ios && manifest.ios.packageId) { widget.setAttribute('ios-CFBundleIdentifier', manifest.ios.packageId); } widget.setAttribute('version', ver); var androidVersionCode = manifest.versionCode || (manifest.android && manifest.android.versionCode); if (!androidVersionCode && manifest.android && manifest.android.version) { androidVersionCode = default_versionCode(manifest.android.version); } setOrDeleteAttribute(widget, 'android-versionCode', androidVersionCode); var iosBundleVersion = manifest.CFBundleVersion || (manifest.ios && manifest.ios.CFBundleVersion); if (!iosBundleVersion && manifest.ios && manifest.ios.version) { iosBundleVersion = default_CFBundleVersion(manifest.ios.version); } setOrDeleteAttribute(widget, 'ios-CFBundleVersion', iosBundleVersion); getOrCreateRootNode('name').textContent = manifest.name || manifest.packageId || 'Your App Name'; getOrCreateRootNode('description').textContent = manifest.description || 'Plain text description of this app'; getOrCreateRootNode('author').textContent = manifest.author || 'Author Name <a@b.com>'; getOrCreateRootNode('content').setAttribute('src', 'plugins/cordova-plugin-chrome-apps-bootstrap/chromeapp.html'); // Set minSdkVersion and targetSdkVersion, corodva-lib copies them to AndoridManifest.xml // Default minSdkVersion is 14 for Android 4.0 (ICS) var minSdkVersion = manifest.minSdkVersion || '14'; setOrCreatePreference('android-minSdkVersion', minSdkVersion); if (manifest.targetSdkVersion) { setOrCreatePreference('android-targetSdkVersion', manifest.targetSdkVersion); } var access; while ((access = $('access'))) { access.parentNode.removeChild(access); } analyzedManifest.whitelist.forEach(function(pattern, index) { var tag = configXmlDom.createElement('access'); tag.setAttribute('origin', pattern); widget.appendChild(tag); }); // If there are any icons, clear out all existing <icon>s if (manifest.icons || (manifest.android && manifest.android.icons) || (manifest.ios && manifest.ios.icons)) { deleteAllChildren(widget, 'icon'); deleteAllChildren(getOrCreatePlatformNode('android'), 'icon'); deleteAllChildren(getOrCreatePlatformNode('ios'), 'icon'); } function createIconTags(platform) { var parentNode = getOrCreatePlatformNode(platform); var iconMap = manifest[platform] && manifest[platform].icons || manifest.icons; if (!iconMap) { return; } var iconSizes = Object.keys(iconMap); if (iconSizes.length) { var defaultIconSrc = iconMap[findLargestNumericKey(iconMap)]; createIconNode(parentNode, 'www/' + defaultIconSrc, null); } iconSizes.forEach(function(size) { createIconNode(parentNode, 'www/' + iconMap[size], size); }); } createIconTags('android'); createIconTags('ios'); if (analyzedManifest.engineName == 'crosswalk' && analyzedManifest.engineVer) { setOrCreatePreference('xwalkVersion', analyzedManifest.engineVer); } else { deletePreference('xwalkVersion'); } }; // Taken from cordova-lib/src/cordova/metadata/android_parser.js function default_versionCode(version) { var nums = version.split('-')[0].split('.'); var versionCode = 0; if (+nums[0]) { versionCode += +nums[0] * 10000; } if (+nums[1]) { versionCode += +nums[1] * 100; } if (+nums[2]) { versionCode += +nums[2]; } return versionCode; } // Taken from cordova-lib/src/cordova/metadata/ios_parser.js function default_CFBundleVersion(version) { return version.split('-')[0]; } |
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| check_reqs.js | 11.64% | (17 / 146) | 0% | (0 / 83) | 0% | (0 / 28) | 11.81% | (17 / 144) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | //#!/usr/bin/env node
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* jshint sub:true */
var shelljs = require('shelljs'),
child_process = require('child_process'),
Q = require('q'),
path = require('path'),
fs = require('fs'),
ROOT = path.join(__dirname, '..', '..');
var CordovaError = require('cordova-common').CordovaError;
var isWindows = process.platform == 'win32';
function forgivingWhichSync(cmd) {
try {
return fs.realpathSync(shelljs.which(cmd));
} catch (e) {
return '';
}
}
function tryCommand(cmd, errMsg, catchStderr) {
var d = Q.defer();
child_process.exec(cmd, function(err, stdout, stderr) {
if (err) d.reject(new CordovaError(errMsg));
// Sometimes it is necessary to return an stderr instead of stdout in case of success, since
// some commands prints theirs output to stderr instead of stdout. 'javac' is the example
else d.resolve((catchStderr ? stderr : stdout).trim());
});
return d.promise;
}
// Get valid target from framework/project.properties
module.exports.get_target = function() {
function extractFromFile(filePath) {
var target = shelljs.grep(/\btarget=/, filePath);
if (!target) {
throw new Error('Could not find android target within: ' + filePath);
}
return target.split('=')[1].trim();
}
if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
return extractFromFile(path.join(ROOT, 'framework', 'project.properties'));
}
if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
// if no target found, we're probably in a project and project.properties is in ROOT.
return extractFromFile(path.join(ROOT, 'project.properties'));
}
throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties'));
};
// Returns a promise. Called only by build and clean commands.
module.exports.check_ant = function() {
return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.')
.then(function (output) {
// Parse Ant version from command output
return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
});
};
// Returns a promise. Called only by build and clean commands.
module.exports.check_gradle = function() {
var sdkDir = process.env['ANDROID_HOME'];
if (!sdkDir)
return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
if (!fs.existsSync(wrapperDir)) {
return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.\n' +
'Looked here: ' + wrapperDir));
}
return Q.when();
};
// Returns a promise.
module.exports.check_java = function() {
var javacPath = forgivingWhichSync('javac');
var hasJavaHome = !!process.env['JAVA_HOME'];
return Q().then(function() {
if (hasJavaHome) {
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
if (!javacPath) {
process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
}
} else {
if (javacPath) {
var msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.';
// OS X has a command for finding JAVA_HOME.
if (fs.existsSync('/usr/libexec/java_home')) {
return tryCommand('/usr/libexec/java_home', msg)
.then(function(stdout) {
process.env['JAVA_HOME'] = stdout.trim();
});
} else {
// See if we can derive it from javac's location.
// fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
var maybeJavaHome = path.dirname(path.dirname(javacPath));
if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
process.env['JAVA_HOME'] = maybeJavaHome;
} else {
throw new CordovaError(msg);
}
}
} else if (isWindows) {
// Try to auto-detect java in the default install paths.
var oldSilent = shelljs.config.silent;
shelljs.config.silent = true;
var firstJdkDir =
shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
shelljs.config.silent = oldSilent;
if (firstJdkDir) {
// shelljs always uses / in paths.
firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
if (!javacPath) {
process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
}
process.env['JAVA_HOME'] = firstJdkDir;
}
}
}
}).then(function() {
var msg =
'Failed to run "java -version", make sure that you have a JDK installed.\n' +
'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
if (process.env['JAVA_HOME']) {
msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
}
return tryCommand('java -version', msg)
.then(function() {
// We use tryCommand with catchStderr = true, because
// javac writes version info to stderr instead of stdout
return tryCommand('javac -version', msg, true);
}).then(function (output) {
var match = /javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
return match && match[1];
});
});
};
// Returns a promise.
module.exports.check_android = function() {
return Q().then(function() {
var androidCmdPath = forgivingWhichSync('android');
var adbInPath = !!forgivingWhichSync('adb');
var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
function maybeSetAndroidHome(value) {
if (!hasAndroidHome && fs.existsSync(value)) {
hasAndroidHome = true;
process.env['ANDROID_HOME'] = value;
}
}
if (!hasAndroidHome && !androidCmdPath) {
if (isWindows) {
// Android Studio 1.0 installer
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
// Android Studio pre-1.0 installer
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
// Stand-alone installer
maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
} else if (process.platform == 'darwin') {
// Android Studio 1.0 installer
maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
// Android Studio pre-1.0 installer
maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
// Stand-alone zip file that user might think to put under /Applications
maybeSetAndroidHome('/Applications/android-sdk-macosx');
maybeSetAndroidHome('/Applications/android-sdk');
}
if (process.env['HOME']) {
// Stand-alone zip file that user might think to put under their home directory
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
}
}
if (hasAndroidHome && !androidCmdPath) {
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
}
if (androidCmdPath && !hasAndroidHome) {
var parentDir = path.dirname(androidCmdPath);
var grandParentDir = path.dirname(parentDir);
if (path.basename(parentDir) == 'tools') {
process.env['ANDROID_HOME'] = path.dirname(parentDir);
hasAndroidHome = true;
} else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
process.env['ANDROID_HOME'] = grandParentDir;
hasAndroidHome = true;
} else {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
'Try reinstall Android SDK or update your PATH to include path to valid SDK directory.');
}
}
if (hasAndroidHome && !adbInPath) {
process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
}
if (!process.env['ANDROID_HOME']) {
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
}
if (!fs.existsSync(process.env['ANDROID_HOME'])) {
throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
'\nTry update it manually to point to valid SDK directory.');
}
});
};
module.exports.getAbsoluteAndroidCmd = function () {
var cmd = forgivingWhichSync('android');
if (process.platform === 'win32') {
return '"' + cmd + '"';
}
return cmd.replace(/(\s)/g, '\\$1');
};
module.exports.check_android_target = function(valid_target) {
// valid_target can look like:
// android-19
// android-L
// Google Inc.:Google APIs:20
// Google Inc.:Glass Development Kit Preview:20
if (!valid_target) valid_target = module.exports.get_target();
var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.';
return tryCommand('android list targets --compact', msg)
.then(function(output) {
var targets = output.split('\n');
if (targets.indexOf(valid_target) >= 0) {
return targets;
}
var androidCmd = module.exports.getAbsoluteAndroidCmd();
throw new CordovaError('Please install Android target: "' + valid_target + '".\n\n' +
'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
'You will require:\n' +
'1. "SDK Platform" for ' + valid_target + '\n' +
'2. "Android SDK Platform-tools (latest)\n' +
'3. "Android SDK Build-tools" (latest)');
});
};
// Returns a promise.
module.exports.run = function() {
return Q.all([this.check_java(), this.check_android().then(this.check_android_target)])
.then(function() {
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
});
};
/**
* Object thar represents one of requirements for current platform.
* @param {String} id The unique identifier for this requirements.
* @param {String} name The name of requirements. Human-readable field.
* @param {String} version The version of requirement installed. In some cases could be an array of strings
* (for example, check_android_target returns an array of android targets installed)
* @param {Boolean} installed Indicates whether the requirement is installed or not
*/
var Requirement = function (id, name, version, installed) {
this.id = id;
this.name = name;
this.installed = installed || false;
this.metadata = {
version: version,
};
};
/**
* Methods that runs all checks one by one and returns a result of checks
* as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
*
* @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
*/
module.exports.check_all = function() {
var requirements = [
new Requirement('java', 'Java JDK'),
new Requirement('androidSdk', 'Android SDK'),
new Requirement('androidTarget', 'Android target'),
new Requirement('gradle', 'Gradle')
];
var checkFns = [
this.check_java,
this.check_android,
this.check_android_target,
this.check_gradle
];
// Then execute requirement checks one-by-one
return checkFns.reduce(function (promise, checkFn, idx) {
// Update each requirement with results
var requirement = requirements[idx];
return promise.then(checkFn)
.then(function (version) {
requirement.installed = true;
requirement.metadata.version = version;
}, function (err) {
requirement.metadata.reason = err instanceof Error ? err.message : err;
});
}, Q())
.then(function () {
// When chain is completed, return requirements array to upstream API
return requirements;
});
};
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| cordova-common.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* jshint node:true */
// For now expose plugman and cordova just as they were in the old repos
exports = module.exports = {
events: require('./src/events'),
superspawn: require('./src/superspawn'),
ActionStack: require('./src/ActionStack'),
CordovaError: require('./src/CordovaError/CordovaError'),
CordovaExternalToolErrorContext: require('./src/CordovaError/CordovaExternalToolErrorContext'),
PlatformJson: require('./src/PlatformJson'),
ConfigParser: require('./src/ConfigParser/ConfigParser.js'),
PluginInfo: require('./src/PluginInfo/PluginInfo.js'),
PluginInfoProvider: require('./src/PluginInfo/PluginInfoProvider.js'),
ConfigChanges: require('./src/ConfigChanges/ConfigChanges.js'),
ConfigKeeper: require('./src/ConfigChanges/ConfigKeeper.js'),
ConfigFile: require('./src/ConfigChanges/ConfigFile.js'),
mungeUtil: require('./src/ConfigChanges/munge-util.js'),
xmlHelpers: require('./src/util/xml-helpers')
};
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| bplistParser.js | 10.68% | (22 / 206) | 0% | (0 / 90) | 0% | (0 / 18) | 10.73% | (22 / 205) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | 'use strict';
// adapted from http://code.google.com/p/plist/source/browse/trunk/src/com/dd/plist/BinaryPropertyListParser.java
var fs = require('fs');
var debug = false;
exports.maxObjectSize = 100 * 1000 * 1000; // 100Meg
exports.maxObjectCount = 32768;
// EPOCH = new SimpleDateFormat("yyyy MM dd zzz").parse("2001 01 01 GMT").getTime();
// ...but that's annoying in a static initializer because it can throw exceptions, ick.
// So we just hardcode the correct value.
var EPOCH = 978307200000;
// UID object definition
var UID = exports.UID = function(id) {
this.UID = id;
}
var parseFile = exports.parseFile = function (fileNameOrBuffer, callback) {
function tryParseBuffer(buffer) {
var err = null;
var result;
try {
result = parseBuffer(buffer);
} catch (ex) {
err = ex;
}
callback(err, result);
}
if (Buffer.isBuffer(fileNameOrBuffer)) {
return tryParseBuffer(fileNameOrBuffer);
} else {
fs.readFile(fileNameOrBuffer, function (err, data) {
if (err) { return callback(err); }
tryParseBuffer(data);
});
}
};
var parseBuffer = exports.parseBuffer = function (buffer) {
var result = {};
// check header
var header = buffer.slice(0, 'bplist'.length).toString('utf8');
if (header !== 'bplist') {
throw new Error("Invalid binary plist. Expected 'bplist' at offset 0.");
}
// Handle trailer, last 32 bytes of the file
var trailer = buffer.slice(buffer.length - 32, buffer.length);
// 6 null bytes (index 0 to 5)
var offsetSize = trailer.readUInt8(6);
if (debug) {
console.log("offsetSize: " + offsetSize);
}
var objectRefSize = trailer.readUInt8(7);
if (debug) {
console.log("objectRefSize: " + objectRefSize);
}
var numObjects = readUInt64BE(trailer, 8);
if (debug) {
console.log("numObjects: " + numObjects);
}
var topObject = readUInt64BE(trailer, 16);
if (debug) {
console.log("topObject: " + topObject);
}
var offsetTableOffset = readUInt64BE(trailer, 24);
if (debug) {
console.log("offsetTableOffset: " + offsetTableOffset);
}
if (numObjects > exports.maxObjectCount) {
throw new Error("maxObjectCount exceeded");
}
// Handle offset table
var offsetTable = [];
for (var i = 0; i < numObjects; i++) {
var offsetBytes = buffer.slice(offsetTableOffset + i * offsetSize, offsetTableOffset + (i + 1) * offsetSize);
offsetTable[i] = readUInt(offsetBytes, 0);
if (debug) {
console.log("Offset for Object #" + i + " is " + offsetTable[i] + " [" + offsetTable[i].toString(16) + "]");
}
}
// Parses an object inside the currently parsed binary property list.
// For the format specification check
// <a href="http://www.opensource.apple.com/source/CF/CF-635/CFBinaryPList.c">
// Apple's binary property list parser implementation</a>.
function parseObject(tableOffset) {
var offset = offsetTable[tableOffset];
var type = buffer[offset];
var objType = (type & 0xF0) >> 4; //First 4 bits
var objInfo = (type & 0x0F); //Second 4 bits
switch (objType) {
case 0x0:
return parseSimple();
case 0x1:
return parseInteger();
case 0x8:
return parseUID();
case 0x2:
return parseReal();
case 0x3:
return parseDate();
case 0x4:
return parseData();
case 0x5: // ASCII
return parsePlistString();
case 0x6: // UTF-16
return parsePlistString(true);
case 0xA:
return parseArray();
case 0xD:
return parseDictionary();
default:
throw new Error("Unhandled type 0x" + objType.toString(16));
}
function parseSimple() {
//Simple
switch (objInfo) {
case 0x0: // null
return null;
case 0x8: // false
return false;
case 0x9: // true
return true;
case 0xF: // filler byte
return null;
default:
throw new Error("Unhandled simple type 0x" + objType.toString(16));
}
}
function parseInteger() {
var length = Math.pow(2, objInfo);
if (length < exports.maxObjectSize) {
return readUInt(buffer.slice(offset + 1, offset + 1 + length));
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
}
function parseUID() {
var length = objInfo + 1;
if (length < exports.maxObjectSize) {
return new UID(readUInt(buffer.slice(offset + 1, offset + 1 + length)));
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
}
function parseReal() {
var length = Math.pow(2, objInfo);
if (length < exports.maxObjectSize) {
var realBuffer = buffer.slice(offset + 1, offset + 1 + length);
if (length === 4) {
return realBuffer.readFloatBE(0);
}
else if (length === 8) {
return realBuffer.readDoubleBE(0);
}
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
}
function parseDate() {
if (objInfo != 0x3) {
console.error("Unknown date type :" + objInfo + ". Parsing anyway...");
}
var dateBuffer = buffer.slice(offset + 1, offset + 9);
return new Date(EPOCH + (1000 * dateBuffer.readDoubleBE(0)));
}
function parseData() {
var dataoffset = 1;
var length = objInfo;
if (objInfo == 0xF) {
var int_type = buffer[offset + 1];
var intType = (int_type & 0xF0) / 0x10;
if (intType != 0x1) {
console.error("0x4: UNEXPECTED LENGTH-INT TYPE! " + intType);
}
var intInfo = int_type & 0x0F;
var intLength = Math.pow(2, intInfo);
dataoffset = 2 + intLength;
if (intLength < 3) {
length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));
} else {
length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));
}
}
if (length < exports.maxObjectSize) {
return buffer.slice(offset + dataoffset, offset + dataoffset + length);
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
}
function parsePlistString (isUtf16) {
isUtf16 = isUtf16 || 0;
var enc = "utf8";
var length = objInfo;
var stroffset = 1;
if (objInfo == 0xF) {
var int_type = buffer[offset + 1];
var intType = (int_type & 0xF0) / 0x10;
if (intType != 0x1) {
console.err("UNEXPECTED LENGTH-INT TYPE! " + intType);
}
var intInfo = int_type & 0x0F;
var intLength = Math.pow(2, intInfo);
var stroffset = 2 + intLength;
if (intLength < 3) {
length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));
} else {
length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));
}
}
// length is String length -> to get byte length multiply by 2, as 1 character takes 2 bytes in UTF-16
length *= (isUtf16 + 1);
if (length < exports.maxObjectSize) {
var plistString = new Buffer(buffer.slice(offset + stroffset, offset + stroffset + length));
if (isUtf16) {
plistString = swapBytes(plistString);
enc = "ucs2";
}
return plistString.toString(enc);
} else {
throw new Error("To little heap space available! Wanted to read " + length + " bytes, but only " + exports.maxObjectSize + " are available.");
}
}
function parseArray() {
var length = objInfo;
var arrayoffset = 1;
if (objInfo == 0xF) {
var int_type = buffer[offset + 1];
var intType = (int_type & 0xF0) / 0x10;
if (intType != 0x1) {
console.error("0xa: UNEXPECTED LENGTH-INT TYPE! " + intType);
}
var intInfo = int_type & 0x0F;
var intLength = Math.pow(2, intInfo);
arrayoffset = 2 + intLength;
if (intLength < 3) {
length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));
} else {
length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));
}
}
if (length * objectRefSize > exports.maxObjectSize) {
throw new Error("To little heap space available!");
}
var array = [];
for (var i = 0; i < length; i++) {
var objRef = readUInt(buffer.slice(offset + arrayoffset + i * objectRefSize, offset + arrayoffset + (i + 1) * objectRefSize));
array[i] = parseObject(objRef);
}
return array;
}
function parseDictionary() {
var length = objInfo;
var dictoffset = 1;
if (objInfo == 0xF) {
var int_type = buffer[offset + 1];
var intType = (int_type & 0xF0) / 0x10;
if (intType != 0x1) {
console.error("0xD: UNEXPECTED LENGTH-INT TYPE! " + intType);
}
var intInfo = int_type & 0x0F;
var intLength = Math.pow(2, intInfo);
dictoffset = 2 + intLength;
if (intLength < 3) {
length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));
} else {
length = readUInt(buffer.slice(offset + 2, offset + 2 + intLength));
}
}
if (length * 2 * objectRefSize > exports.maxObjectSize) {
throw new Error("To little heap space available!");
}
if (debug) {
console.log("Parsing dictionary #" + tableOffset);
}
var dict = {};
for (var i = 0; i < length; i++) {
var keyRef = readUInt(buffer.slice(offset + dictoffset + i * objectRefSize, offset + dictoffset + (i + 1) * objectRefSize));
var valRef = readUInt(buffer.slice(offset + dictoffset + (length * objectRefSize) + i * objectRefSize, offset + dictoffset + (length * objectRefSize) + (i + 1) * objectRefSize));
var key = parseObject(keyRef);
var val = parseObject(valRef);
if (debug) {
console.log(" DICT #" + tableOffset + ": Mapped " + key + " to " + val);
}
dict[key] = val;
}
return dict;
}
}
return [ parseObject(topObject) ];
};
function readUInt(buffer, start) {
start = start || 0;
var l = 0;
for (var i = start; i < buffer.length; i++) {
l <<= 8;
l |= buffer[i] & 0xFF;
}
return l;
}
// we're just going to toss the high order bits because javascript doesn't have 64-bit ints
function readUInt64BE(buffer, start) {
var data = buffer.slice(start, start + 8);
return data.readUInt32BE(4, 8);
}
function swapBytes(buffer) {
var len = buffer.length;
for (var i = 0; i < len; i += 2) {
var a = buffer[i];
buffer[i] = buffer[i+1];
buffer[i+1] = a;
}
return buffer;
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| index.js | 100% | (6 / 6) | 100% | (0 / 0) | 100% | (1 / 1) | 100% | (6 / 6) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | 1 1 1 1 187 1 | var map = {
'org.apache.cordova.battery-status':'cordova-plugin-battery-status',
'org.apache.cordova.camera':'cordova-plugin-camera',
'org.apache.cordova.console':'cordova-plugin-console',
'org.apache.cordova.contacts':'cordova-plugin-contacts',
'org.apache.cordova.device':'cordova-plugin-device',
'org.apache.cordova.device-motion':'cordova-plugin-device-motion',
'org.apache.cordova.device-orientation':'cordova-plugin-device-orientation',
'org.apache.cordova.dialogs':'cordova-plugin-dialogs',
'org.apache.cordova.file':'cordova-plugin-file',
'org.apache.cordova.file-transfer':'cordova-plugin-file-transfer',
'org.apache.cordova.geolocation':'cordova-plugin-geolocation',
'org.apache.cordova.globalization':'cordova-plugin-globalization',
'org.apache.cordova.inappbrowser':'cordova-plugin-inappbrowser',
'org.apache.cordova.media':'cordova-plugin-media',
'org.apache.cordova.media-capture':'cordova-plugin-media-capture',
'org.apache.cordova.network-information':'cordova-plugin-network-information',
'org.apache.cordova.splashscreen':'cordova-plugin-splashscreen',
'org.apache.cordova.statusbar':'cordova-plugin-statusbar',
'org.apache.cordova.vibration':'cordova-plugin-vibration',
'org.apache.cordova.test-framework':'cordova-plugin-test-framework',
'com.msopentech.websql' : 'cordova-plugin-websql',
'com.msopentech.indexeddb' : 'cordova-plugin-indexeddb',
'com.microsoft.aad.adal' : 'cordova-plugin-ms-adal',
'com.microsoft.capptain' : 'capptain-cordova',
'com.microsoft.services.aadgraph' : 'cordova-plugin-ms-aad-graph',
'com.microsoft.services.files' : 'cordova-plugin-ms-files',
'om.microsoft.services.outlook' : 'cordova-plugin-ms-outlook',
'com.pbakondy.sim' : 'cordova-plugin-sim',
'android.support.v4' : 'cordova-plugin-android-support-v4',
'android.support.v7-appcompat' : 'cordova-plugin-android-support-v7-appcompat',
'com.google.playservices' : 'cordova-plugin-googleplayservices',
'com.google.cordova.admob' : 'cordova-plugin-admobpro',
'com.rjfun.cordova.extension' : 'cordova-plugin-extension',
'com.rjfun.cordova.plugin.admob' : 'cordova-plugin-admob',
'com.rjfun.cordova.flurryads' : 'cordova-plugin-flurry',
'com.rjfun.cordova.facebookads' : 'cordova-plugin-facebookads',
'com.rjfun.cordova.httpd' : 'cordova-plugin-httpd',
'com.rjfun.cordova.iad' : 'cordova-plugin-iad',
'com.rjfun.cordova.iflyspeech' : 'cordova-plugin-iflyspeech',
'com.rjfun.cordova.lianlianpay' : 'cordova-plugin-lianlianpay',
'com.rjfun.cordova.mobfox' : 'cordova-plugin-mobfox',
'com.rjfun.cordova.mopub' : 'cordova-plugin-mopub',
'com.rjfun.cordova.mmedia' : 'cordova-plugin-mmedia',
'com.rjfun.cordova.nativeaudio' : 'cordova-plugin-nativeaudio',
'com.rjfun.cordova.plugin.paypalmpl' : 'cordova-plugin-paypalmpl',
'com.rjfun.cordova.smartadserver' : 'cordova-plugin-smartadserver',
'com.rjfun.cordova.sms' : 'cordova-plugin-sms',
'com.rjfun.cordova.wifi' : 'cordova-plugin-wifi',
'com.ohh2ahh.plugins.appavailability' : 'cordova-plugin-appavailability',
'org.adapt-it.cordova.fonts' : 'cordova-plugin-fonts',
'de.martinreinhardt.cordova.plugins.barcodeScanner' : 'cordova-plugin-barcodescanner',
'de.martinreinhardt.cordova.plugins.urlhandler' : 'cordova-plugin-urlhandler',
'de.martinreinhardt.cordova.plugins.email' : 'cordova-plugin-email',
'de.martinreinhardt.cordova.plugins.certificates' : 'cordova-plugin-certificates',
'de.martinreinhardt.cordova.plugins.sqlite' : 'cordova-plugin-sqlite',
'fr.smile.cordova.fileopener' : 'cordova-plugin-fileopener',
'org.smile.websqldatabase.initializer' : 'cordova-plugin-websqldatabase-initializer',
'org.smile.websqldatabase.wpdb' : 'cordova-plugin-websqldatabase',
'org.jboss.aerogear.cordova.push' : 'aerogear-cordova-push',
'org.jboss.aerogear.cordova.oauth2' : 'aerogear-cordova-oauth2',
'org.jboss.aerogear.cordova.geo' : 'aerogear-cordova-geo',
'org.jboss.aerogear.cordova.crypto' : 'aerogear-cordova-crypto',
'org.jboss.aerogaer.cordova.otp' : 'aerogear-cordova-otp',
'uk.co.ilee.applewatch' : 'cordova-plugin-apple-watch',
'uk.co.ilee.directions' : 'cordova-plugin-directions',
'uk.co.ilee.gamecenter' : 'cordova-plugin-game-center',
'uk.co.ilee.jailbreakdetection' : 'cordova-plugin-jailbreak-detection',
'uk.co.ilee.nativetransitions' : 'cordova-plugin-native-transitions',
'uk.co.ilee.pedometer' : 'cordova-plugin-pedometer',
'uk.co.ilee.shake' : 'cordova-plugin-shake',
'uk.co.ilee.touchid' : 'cordova-plugin-touchid',
'com.knowledgecode.cordova.websocket' : 'cordova-plugin-websocket',
'com.elixel.plugins.settings' : 'cordova-plugin-settings',
'com.cowbell.cordova.geofence' : 'cordova-plugin-geofence',
'com.blackberry.community.preventsleep' : 'cordova-plugin-preventsleep',
'com.blackberry.community.gamepad' : 'cordova-plugin-gamepad',
'com.blackberry.community.led' : 'cordova-plugin-led',
'com.blackberry.community.thumbnail' : 'cordova-plugin-thumbnail',
'com.blackberry.community.mediakeys' : 'cordova-plugin-mediakeys',
'com.blackberry.community.simplebtlehrplugin' : 'cordova-plugin-bluetoothheartmonitor',
'com.blackberry.community.simplebeaconplugin' : 'cordova-plugin-bluetoothibeacon',
'com.blackberry.community.simplebtsppplugin' : 'cordova-plugin-bluetoothspp',
'com.blackberry.community.clipboard' : 'cordova-plugin-clipboard',
'com.blackberry.community.curl' : 'cordova-plugin-curl',
'com.blackberry.community.qt' : 'cordova-plugin-qtbridge',
'com.blackberry.community.upnp' : 'cordova-plugin-upnp',
'com.blackberry.community.PasswordCrypto' : 'cordova-plugin-password-crypto',
'com.blackberry.community.deviceinfoplugin' : 'cordova-plugin-deviceinfo',
'com.blackberry.community.gsecrypto' : 'cordova-plugin-bb-crypto',
'com.blackberry.community.mongoose' : 'cordova-plugin-mongoose',
'com.blackberry.community.sysdialog' : 'cordova-plugin-bb-sysdialog',
'com.blackberry.community.screendisplay' : 'cordova-plugin-screendisplay',
'com.blackberry.community.messageplugin' : 'cordova-plugin-bb-messageretrieve',
'com.blackberry.community.emailsenderplugin' : 'cordova-plugin-emailsender',
'com.blackberry.community.audiometadata' : 'cordova-plugin-audiometadata',
'com.blackberry.community.deviceemails' : 'cordova-plugin-deviceemails',
'com.blackberry.community.audiorecorder' : 'cordova-plugin-audiorecorder',
'com.blackberry.community.vibration' : 'cordova-plugin-vibrate-intense',
'com.blackberry.community.SMSPlugin' : 'cordova-plugin-bb-sms',
'com.blackberry.community.extractZipFile' : 'cordova-plugin-bb-zip',
'com.blackberry.community.lowlatencyaudio' : 'cordova-plugin-bb-nativeaudio',
'com.blackberry.community.barcodescanner' : 'phonegap-plugin-barcodescanner',
'com.blackberry.app' : 'cordova-plugin-bb-app',
'com.blackberry.bbm.platform' : 'cordova-plugin-bbm',
'com.blackberry.connection' : 'cordova-plugin-bb-connection',
'com.blackberry.identity' : 'cordova-plugin-bb-identity',
'com.blackberry.invoke.card' : 'cordova-plugin-bb-card',
'com.blackberry.invoke' : 'cordova-plugin-bb-invoke',
'com.blackberry.invoked' : 'cordova-plugin-bb-invoked',
'com.blackberry.io.filetransfer' : 'cordova-plugin-bb-filetransfer',
'com.blackberry.io' : 'cordova-plugin-bb-io',
'com.blackberry.notification' : 'cordova-plugin-bb-notification',
'com.blackberry.payment' : 'cordova-plugin-bb-payment',
'com.blackberry.pim.calendar' : 'cordova-plugin-bb-calendar',
'com.blackberry.pim.contacts' : 'cordova-plugin-bb-contacts',
'com.blackberry.pim.lib' : 'cordova-plugin-bb-pimlib',
'com.blackberry.push' : 'cordova-plugin-bb-push',
'com.blackberry.screenshot' : 'cordova-plugin-screenshot',
'com.blackberry.sensors' : 'cordova-plugin-bb-sensors',
'com.blackberry.system' : 'cordova-plugin-bb-system',
'com.blackberry.ui.contextmenu' : 'cordova-plugin-bb-ctxmenu',
'com.blackberry.ui.cover' : 'cordova-plugin-bb-cover',
'com.blackberry.ui.dialog' : 'cordova-plugin-bb-dialog',
'com.blackberry.ui.input' : 'cordova-plugin-touch-keyboard',
'com.blackberry.ui.toast' : 'cordova-plugin-toast',
'com.blackberry.user.identity' : 'cordova-plugin-bb-idservice',
'com.blackberry.utils' : 'cordova-plugin-bb-utils',
'net.yoik.cordova.plugins.screenorientation' : 'cordova-plugin-screen-orientation',
'com.phonegap.plugins.barcodescanner' : 'phonegap-plugin-barcodescanner',
'com.manifoldjs.hostedwebapp' : 'cordova-plugin-hostedwebapp',
'com.initialxy.cordova.themeablebrowser' : 'cordova-plugin-themeablebrowser',
'gr.denton.photosphere' : 'cordova-plugin-panoramaviewer',
'nl.x-services.plugins.actionsheet' : 'cordova-plugin-actionsheet',
'nl.x-services.plugins.socialsharing' : 'cordova-plugin-x-socialsharing',
'nl.x-services.plugins.googleplus' : 'cordova-plugin-googleplus',
'nl.x-services.plugins.insomnia' : 'cordova-plugin-insomnia',
'nl.x-services.plugins.toast' : 'cordova-plugin-x-toast',
'nl.x-services.plugins.calendar' : 'cordova-plugin-calendar',
'nl.x-services.plugins.launchmyapp' : 'cordova-plugin-customurlscheme',
'nl.x-services.plugins.flashlight' : 'cordova-plugin-flashlight',
'nl.x-services.plugins.sslcertificatechecker' : 'cordova-plugin-sslcertificatechecker',
'com.bridge.open' : 'cordova-open',
'com.bridge.safe' : 'cordova-safe',
'com.disusered.open' : 'cordova-open',
'com.disusered.safe' : 'cordova-safe',
'me.apla.cordova.app-preferences' : 'cordova-plugin-app-preferences',
'com.konotor.cordova' : 'cordova-plugin-konotor',
'io.intercom.cordova' : 'cordova-plugin-intercom',
'com.onesignal.plugins.onesignal' : 'onesignal-cordova-plugin',
'com.danjarvis.document-contract': 'cordova-plugin-document-contract',
'com.eface2face.iosrtc' : 'cordova-plugin-iosrtc',
'com.mobileapptracking.matplugin' : 'cordova-plugin-tune',
'com.marianhello.cordova.background-geolocation' : 'cordova-plugin-mauron85-background-geolocation',
'fr.louisbl.cordova.locationservices' : 'cordova-plugin-locationservices',
'fr.louisbl.cordova.gpslocation' : 'cordova-plugin-gpslocation',
'com.hiliaox.weibo' : 'cordova-plugin-weibo',
'com.uxcam.cordova.plugin' : 'cordova-uxcam',
'de.fastr.phonegap.plugins.downloader' : 'cordova-plugin-fastrde-downloader',
'de.fastr.phonegap.plugins.injectView' : 'cordova-plugin-fastrde-injectview',
'de.fastr.phonegap.plugins.CheckGPS' : 'cordova-plugin-fastrde-checkgps',
'de.fastr.phonegap.plugins.md5chksum' : ' cordova-plugin-fastrde-md5',
'io.repro.cordova' : 'cordova-plugin-repro',
're.notifica.cordova': 'cordova-plugin-notificare-push',
'com.megster.cordova.ble': 'cordova-plugin-ble-central',
'com.megster.cordova.bluetoothserial': 'cordova-plugin-bluetooth-serial',
'com.megster.cordova.rfduino': 'cordova-plugin-rfduino',
'cz.velda.cordova.plugin.devicefeedback': 'cordova-plugin-velda-devicefeedback',
'cz.Velda.cordova.plugin.devicefeedback': 'cordova-plugin-velda-devicefeedback',
'org.scriptotek.appinfo': 'cordova-plugin-appinfo',
'com.yezhiming.cordova.appinfo': 'cordova-plugin-appinfo',
'pl.makingwaves.estimotebeacons': 'cordova-plugin-estimote',
'com.evothings.ble': 'cordova-plugin-ble',
'com.appsee.plugin' : 'cordova-plugin-appsee',
'am.armsoft.plugins.listpicker': 'cordova-plugin-listpicker',
'com.pushbots.push': 'pushbots-cordova-plugin',
'com.admob.google': 'cordova-admob',
'admob.ads.google': 'cordova-admob-ads',
'admob.google.plugin': 'admob-google',
'com.admob.admobads': 'admob-ads',
'com.connectivity.monitor': 'cordova-connectivity-monitor',
'com.ios.libgoogleadmobads': 'cordova-libgoogleadmobads',
'com.google.play.services': 'cordova-google-play-services',
'android.support.v13': 'cordova-android-support-v13',
'android.support.v4': 'cordova-android-support-v4',
'com.analytics.google': 'cordova-plugin-analytics',
'com.analytics.adid.google': 'cordova-plugin-analytics-adid',
'com.chariotsolutions.nfc.plugin': 'phonegap-nfc',
'com.samz.mixpanel': 'cordova-plugin-mixpanel'
}
module.exports.oldToNew = map;
var reverseMap = {};
Object.keys(map).forEach(function(elem){
reverseMap[map[elem]] = elem;
})
module.exports.newToOld = reverseMap;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | exports.alphasort = alphasort exports.alphasorti = alphasorti exports.setopts = setopts exports.ownProp = ownProp exports.makeAbs = makeAbs exports.finish = finish exports.mark = mark exports.isIgnored = isIgnored exports.childrenIgnored = childrenIgnored function ownProp (obj, field) { return Object.prototype.hasOwnProperty.call(obj, field) } var path = require("path") var minimatch = require("minimatch") var isAbsolute = require("path-is-absolute") var Minimatch = minimatch.Minimatch function alphasorti (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()) } function alphasort (a, b) { return a.localeCompare(b) } function setupIgnores (self, options) { self.ignore = options.ignore || [] if (!Array.isArray(self.ignore)) self.ignore = [self.ignore] if (self.ignore.length) { self.ignore = self.ignore.map(ignoreMap) } } function ignoreMap (pattern) { var gmatcher = null if (pattern.slice(-3) === '/**') { var gpattern = pattern.replace(/(\/\*\*)+$/, '') gmatcher = new Minimatch(gpattern) } return { matcher: new Minimatch(pattern), gmatcher: gmatcher } } function setopts (self, pattern, options) { if (!options) options = {} // base-matching: just use globstar for that. if (options.matchBase && -1 === pattern.indexOf("/")) { if (options.noglobstar) { throw new Error("base matching requires globstar") } pattern = "**/" + pattern } self.silent = !!options.silent self.pattern = pattern self.strict = options.strict !== false self.realpath = !!options.realpath self.realpathCache = options.realpathCache || Object.create(null) self.follow = !!options.follow self.dot = !!options.dot self.mark = !!options.mark self.nodir = !!options.nodir if (self.nodir) self.mark = true self.sync = !!options.sync self.nounique = !!options.nounique self.nonull = !!options.nonull self.nosort = !!options.nosort self.nocase = !!options.nocase self.stat = !!options.stat self.noprocess = !!options.noprocess self.maxLength = options.maxLength || Infinity self.cache = options.cache || Object.create(null) self.statCache = options.statCache || Object.create(null) self.symlinks = options.symlinks || Object.create(null) setupIgnores(self, options) self.changedCwd = false var cwd = process.cwd() if (!ownProp(options, "cwd")) self.cwd = cwd else { self.cwd = options.cwd self.changedCwd = path.resolve(options.cwd) !== cwd } self.root = options.root || path.resolve(self.cwd, "/") self.root = path.resolve(self.root) if (process.platform === "win32") self.root = self.root.replace(/\\/g, "/") self.nomount = !!options.nomount // disable comments and negation unless the user explicitly // passes in false as the option. options.nonegate = options.nonegate === false ? false : true options.nocomment = options.nocomment === false ? false : true deprecationWarning(options) self.minimatch = new Minimatch(pattern, options) self.options = self.minimatch.options } // TODO(isaacs): remove entirely in v6 // exported to reset in tests exports.deprecationWarned function deprecationWarning(options) { if (!options.nonegate || !options.nocomment) { if (process.noDeprecation !== true && !exports.deprecationWarned) { var msg = 'glob WARNING: comments and negation will be disabled in v6' if (process.throwDeprecation) throw new Error(msg) else if (process.traceDeprecation) console.trace(msg) else console.error(msg) exports.deprecationWarned = true } } } function finish (self) { var nou = self.nounique var all = nou ? [] : Object.create(null) for (var i = 0, l = self.matches.length; i < l; i ++) { var matches = self.matches[i] if (!matches || Object.keys(matches).length === 0) { if (self.nonull) { // do like the shell, and spit out the literal glob var literal = self.minimatch.globSet[i] if (nou) all.push(literal) else all[literal] = true } } else { // had matches var m = Object.keys(matches) if (nou) all.push.apply(all, m) else m.forEach(function (m) { all[m] = true }) } } if (!nou) all = Object.keys(all) if (!self.nosort) all = all.sort(self.nocase ? alphasorti : alphasort) // at *some* point we statted all of these if (self.mark) { for (var i = 0; i < all.length; i++) { all[i] = self._mark(all[i]) } if (self.nodir) { all = all.filter(function (e) { return !(/\/$/.test(e)) }) } } if (self.ignore.length) all = all.filter(function(m) { return !isIgnored(self, m) }) self.found = all } function mark (self, p) { var abs = makeAbs(self, p) var c = self.cache[abs] var m = p if (c) { var isDir = c === 'DIR' || Array.isArray(c) var slash = p.slice(-1) === '/' if (isDir && !slash) m += '/' else if (!isDir && slash) m = m.slice(0, -1) if (m !== p) { var mabs = makeAbs(self, m) self.statCache[mabs] = self.statCache[abs] self.cache[mabs] = self.cache[abs] } } return m } // lotta situps... function makeAbs (self, f) { var abs = f if (f.charAt(0) === '/') { abs = path.join(self.root, f) } else if (isAbsolute(f) || f === '') { abs = f } else if (self.changedCwd) { abs = path.resolve(self.cwd, f) } else { abs = path.resolve(f) } return abs } // Return true, if pattern ends with globstar '**', for the accompanying parent directory. // Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents function isIgnored (self, path) { if (!self.ignore.length) return false return self.ignore.some(function(item) { return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) }) } function childrenIgnored (self, path) { if (!self.ignore.length) return false return self.ignore.some(function(item) { return !!(item.gmatcher && item.gmatcher.match(path)) }) } |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | // Approach:
//
// 1. Get the minimatch set
// 2. For each pattern in the set, PROCESS(pattern, false)
// 3. Store matches per-set, then uniq them
//
// PROCESS(pattern, inGlobStar)
// Get the first [n] items from pattern that are all strings
// Join these together. This is PREFIX.
// If there is no more remaining, then stat(PREFIX) and
// add to matches if it succeeds. END.
//
// If inGlobStar and PREFIX is symlink and points to dir
// set ENTRIES = []
// else readdir(PREFIX) as ENTRIES
// If fail, END
//
// with ENTRIES
// If pattern[n] is GLOBSTAR
// // handle the case where the globstar match is empty
// // by pruning it out, and testing the resulting pattern
// PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
// // handle other cases.
// for ENTRY in ENTRIES (not dotfiles)
// // attach globstar + tail onto the entry
// // Mark that this entry is a globstar match
// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
//
// else // not globstar
// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
// Test ENTRY against pattern[n]
// If fails, continue
// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
//
// Caveat:
// Cache all stats and readdirs results to minimize syscall. Since all
// we ever care about is existence and directory-ness, we can just keep
// `true` for files, and [children,...] for directories, or `false` for
// things that don't exist.
module.exports = glob
var fs = require('fs')
var minimatch = require('minimatch')
var Minimatch = minimatch.Minimatch
var inherits = require('inherits')
var EE = require('events').EventEmitter
var path = require('path')
var assert = require('assert')
var isAbsolute = require('path-is-absolute')
var globSync = require('./sync.js')
var common = require('./common.js')
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
var ownProp = common.ownProp
var inflight = require('inflight')
var util = require('util')
var childrenIgnored = common.childrenIgnored
var isIgnored = common.isIgnored
var once = require('once')
function glob (pattern, options, cb) {
if (typeof options === 'function') cb = options, options = {}
if (!options) options = {}
if (options.sync) {
if (cb)
throw new TypeError('callback provided to sync glob')
return globSync(pattern, options)
}
return new Glob(pattern, options, cb)
}
glob.sync = globSync
var GlobSync = glob.GlobSync = globSync.GlobSync
// old api surface
glob.glob = glob
glob.hasMagic = function (pattern, options_) {
var options = util._extend({}, options_)
options.noprocess = true
var g = new Glob(pattern, options)
var set = g.minimatch.set
if (set.length > 1)
return true
for (var j = 0; j < set[0].length; j++) {
if (typeof set[0][j] !== 'string')
return true
}
return false
}
glob.Glob = Glob
inherits(Glob, EE)
function Glob (pattern, options, cb) {
if (typeof options === 'function') {
cb = options
options = null
}
if (options && options.sync) {
if (cb)
throw new TypeError('callback provided to sync glob')
return new GlobSync(pattern, options)
}
if (!(this instanceof Glob))
return new Glob(pattern, options, cb)
setopts(this, pattern, options)
this._didRealPath = false
// process each pattern in the minimatch set
var n = this.minimatch.set.length
// The matches are stored as {<filename>: true,...} so that
// duplicates are automagically pruned.
// Later, we do an Object.keys() on these.
// Keep them as a list so we can fill in when nonull is set.
this.matches = new Array(n)
if (typeof cb === 'function') {
cb = once(cb)
this.on('error', cb)
this.on('end', function (matches) {
cb(null, matches)
})
}
var self = this
var n = this.minimatch.set.length
this._processing = 0
this.matches = new Array(n)
this._emitQueue = []
this._processQueue = []
this.paused = false
if (this.noprocess)
return this
if (n === 0)
return done()
for (var i = 0; i < n; i ++) {
this._process(this.minimatch.set[i], i, false, done)
}
function done () {
--self._processing
if (self._processing <= 0)
self._finish()
}
}
Glob.prototype._finish = function () {
assert(this instanceof Glob)
if (this.aborted)
return
if (this.realpath && !this._didRealpath)
return this._realpath()
common.finish(this)
this.emit('end', this.found)
}
Glob.prototype._realpath = function () {
if (this._didRealpath)
return
this._didRealpath = true
var n = this.matches.length
if (n === 0)
return this._finish()
var self = this
for (var i = 0; i < this.matches.length; i++)
this._realpathSet(i, next)
function next () {
if (--n === 0)
self._finish()
}
}
Glob.prototype._realpathSet = function (index, cb) {
var matchset = this.matches[index]
if (!matchset)
return cb()
var found = Object.keys(matchset)
var self = this
var n = found.length
if (n === 0)
return cb()
var set = this.matches[index] = Object.create(null)
found.forEach(function (p, i) {
// If there's a problem with the stat, then it means that
// one or more of the links in the realpath couldn't be
// resolved. just return the abs value in that case.
p = self._makeAbs(p)
fs.realpath(p, self.realpathCache, function (er, real) {
if (!er)
set[real] = true
else if (er.syscall === 'stat')
set[p] = true
else
self.emit('error', er) // srsly wtf right here
if (--n === 0) {
self.matches[index] = set
cb()
}
})
})
}
Glob.prototype._mark = function (p) {
return common.mark(this, p)
}
Glob.prototype._makeAbs = function (f) {
return common.makeAbs(this, f)
}
Glob.prototype.abort = function () {
this.aborted = true
this.emit('abort')
}
Glob.prototype.pause = function () {
if (!this.paused) {
this.paused = true
this.emit('pause')
}
}
Glob.prototype.resume = function () {
if (this.paused) {
this.emit('resume')
this.paused = false
if (this._emitQueue.length) {
var eq = this._emitQueue.slice(0)
this._emitQueue.length = 0
for (var i = 0; i < eq.length; i ++) {
var e = eq[i]
this._emitMatch(e[0], e[1])
}
}
if (this._processQueue.length) {
var pq = this._processQueue.slice(0)
this._processQueue.length = 0
for (var i = 0; i < pq.length; i ++) {
var p = pq[i]
this._processing--
this._process(p[0], p[1], p[2], p[3])
}
}
}
}
Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
assert(this instanceof Glob)
assert(typeof cb === 'function')
if (this.aborted)
return
this._processing++
if (this.paused) {
this._processQueue.push([pattern, index, inGlobStar, cb])
return
}
//console.error('PROCESS %d', this._processing, pattern)
// Get the first [n] parts of pattern that are all strings.
var n = 0
while (typeof pattern[n] === 'string') {
n ++
}
// now n is the index of the first one that is *not* a string.
// see if there's anything else
var prefix
switch (n) {
// if not, then this is rather simple
case pattern.length:
this._processSimple(pattern.join('/'), index, cb)
return
case 0:
// pattern *starts* with some non-trivial item.
// going to readdir(cwd), but not include the prefix in matches.
prefix = null
break
default:
// pattern has some string bits in the front.
// whatever it starts with, whether that's 'absolute' like /foo/bar,
// or 'relative' like '../baz'
prefix = pattern.slice(0, n).join('/')
break
}
var remain = pattern.slice(n)
// get the list of entries.
var read
if (prefix === null)
read = '.'
else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
if (!prefix || !isAbsolute(prefix))
prefix = '/' + prefix
read = prefix
} else
read = prefix
var abs = this._makeAbs(read)
//if ignored, skip _processing
if (childrenIgnored(this, read))
return cb()
var isGlobStar = remain[0] === minimatch.GLOBSTAR
if (isGlobStar)
this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb)
else
this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb)
}
Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
var self = this
this._readdir(abs, inGlobStar, function (er, entries) {
return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
})
}
Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
// if the abs isn't a dir, then nothing can match!
if (!entries)
return cb()
// It will only match dot entries if it starts with a dot, or if
// dot is set. Stuff like @(.foo|.bar) isn't allowed.
var pn = remain[0]
var negate = !!this.minimatch.negate
var rawGlob = pn._glob
var dotOk = this.dot || rawGlob.charAt(0) === '.'
var matchedEntries = []
for (var i = 0; i < entries.length; i++) {
var e = entries[i]
if (e.charAt(0) !== '.' || dotOk) {
var m
if (negate && !prefix) {
m = !e.match(pn)
} else {
m = e.match(pn)
}
if (m)
matchedEntries.push(e)
}
}
//console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
var len = matchedEntries.length
// If there are no matched entries, then nothing matches.
if (len === 0)
return cb()
// if this is the last remaining pattern bit, then no need for
// an additional stat *unless* the user has specified mark or
// stat explicitly. We know they exist, since readdir returned
// them.
if (remain.length === 1 && !this.mark && !this.stat) {
if (!this.matches[index])
this.matches[index] = Object.create(null)
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
if (prefix) {
if (prefix !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
if (e.charAt(0) === '/' && !this.nomount) {
e = path.join(this.root, e)
}
this._emitMatch(index, e)
}
// This was the last one, and no stats were needed
return cb()
}
// now test all matched entries as stand-ins for that part
// of the pattern.
remain.shift()
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
var newPattern
if (prefix) {
if (prefix !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
this._process([e].concat(remain), index, inGlobStar, cb)
}
cb()
}
Glob.prototype._emitMatch = function (index, e) {
if (this.aborted)
return
if (this.matches[index][e])
return
if (isIgnored(this, e))
return
if (this.paused) {
this._emitQueue.push([index, e])
return
}
var abs = this._makeAbs(e)
if (this.nodir) {
var c = this.cache[abs]
if (c === 'DIR' || Array.isArray(c))
return
}
if (this.mark)
e = this._mark(e)
this.matches[index][e] = true
var st = this.statCache[abs]
if (st)
this.emit('stat', e, st)
this.emit('match', e)
}
Glob.prototype._readdirInGlobStar = function (abs, cb) {
if (this.aborted)
return
// follow all symlinked directories forever
// just proceed as if this is a non-globstar situation
if (this.follow)
return this._readdir(abs, false, cb)
var lstatkey = 'lstat\0' + abs
var self = this
var lstatcb = inflight(lstatkey, lstatcb_)
if (lstatcb)
fs.lstat(abs, lstatcb)
function lstatcb_ (er, lstat) {
if (er)
return cb()
var isSym = lstat.isSymbolicLink()
self.symlinks[abs] = isSym
// If it's not a symlink or a dir, then it's definitely a regular file.
// don't bother doing a readdir in that case.
if (!isSym && !lstat.isDirectory()) {
self.cache[abs] = 'FILE'
cb()
} else
self._readdir(abs, false, cb)
}
}
Glob.prototype._readdir = function (abs, inGlobStar, cb) {
if (this.aborted)
return
cb = inflight('readdir\0'+abs+'\0'+inGlobStar, cb)
if (!cb)
return
//console.error('RD %j %j', +inGlobStar, abs)
if (inGlobStar && !ownProp(this.symlinks, abs))
return this._readdirInGlobStar(abs, cb)
if (ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (!c || c === 'FILE')
return cb()
if (Array.isArray(c))
return cb(null, c)
}
var self = this
fs.readdir(abs, readdirCb(this, abs, cb))
}
function readdirCb (self, abs, cb) {
return function (er, entries) {
if (er)
self._readdirError(abs, er, cb)
else
self._readdirEntries(abs, entries, cb)
}
}
Glob.prototype._readdirEntries = function (abs, entries, cb) {
if (this.aborted)
return
// if we haven't asked to stat everything, then just
// assume that everything in there exists, so we can avoid
// having to stat it a second time.
if (!this.mark && !this.stat) {
for (var i = 0; i < entries.length; i ++) {
var e = entries[i]
if (abs === '/')
e = abs + e
else
e = abs + '/' + e
this.cache[e] = true
}
}
this.cache[abs] = entries
return cb(null, entries)
}
Glob.prototype._readdirError = function (f, er, cb) {
if (this.aborted)
return
// handle errors, and cache the information
switch (er.code) {
case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
case 'ENOTDIR': // totally normal. means it *does* exist.
this.cache[this._makeAbs(f)] = 'FILE'
break
case 'ENOENT': // not terribly unusual
case 'ELOOP':
case 'ENAMETOOLONG':
case 'UNKNOWN':
this.cache[this._makeAbs(f)] = false
break
default: // some unusual error. Treat as failure.
this.cache[this._makeAbs(f)] = false
if (this.strict) {
this.emit('error', er)
// If the error is handled, then we abort
// if not, we threw out of here
this.abort()
}
if (!this.silent)
console.error('glob error', er)
break
}
return cb()
}
Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
var self = this
this._readdir(abs, inGlobStar, function (er, entries) {
self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
})
}
Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
//console.error('pgs2', prefix, remain[0], entries)
// no entries means not a dir, so it can never have matches
// foo.txt/** doesn't match foo.txt
if (!entries)
return cb()
// test without the globstar, and with every child both below
// and replacing the globstar.
var remainWithoutGlobStar = remain.slice(1)
var gspref = prefix ? [ prefix ] : []
var noGlobStar = gspref.concat(remainWithoutGlobStar)
// the noGlobStar pattern exits the inGlobStar state
this._process(noGlobStar, index, false, cb)
var isSym = this.symlinks[abs]
var len = entries.length
// If it's a symlink, and we're in a globstar, then stop
if (isSym && inGlobStar)
return cb()
for (var i = 0; i < len; i++) {
var e = entries[i]
if (e.charAt(0) === '.' && !this.dot)
continue
// these two cases enter the inGlobStar state
var instead = gspref.concat(entries[i], remainWithoutGlobStar)
this._process(instead, index, true, cb)
var below = gspref.concat(entries[i], remain)
this._process(below, index, true, cb)
}
cb()
}
Glob.prototype._processSimple = function (prefix, index, cb) {
// XXX review this. Shouldn't it be doing the mounting etc
// before doing stat? kinda weird?
var self = this
this._stat(prefix, function (er, exists) {
self._processSimple2(prefix, index, er, exists, cb)
})
}
Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
//console.error('ps2', prefix, exists)
if (!this.matches[index])
this.matches[index] = Object.create(null)
// If it doesn't exist, then just mark the lack of results
if (!exists)
return cb()
if (prefix && isAbsolute(prefix) && !this.nomount) {
var trail = /[\/\\]$/.test(prefix)
if (prefix.charAt(0) === '/') {
prefix = path.join(this.root, prefix)
} else {
prefix = path.resolve(this.root, prefix)
if (trail)
prefix += '/'
}
}
if (process.platform === 'win32')
prefix = prefix.replace(/\\/g, '/')
// Mark this as a match
this._emitMatch(index, prefix)
cb()
}
// Returns either 'DIR', 'FILE', or false
Glob.prototype._stat = function (f, cb) {
var abs = this._makeAbs(f)
var needDir = f.slice(-1) === '/'
if (f.length > this.maxLength)
return cb()
if (!this.stat && ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (Array.isArray(c))
c = 'DIR'
// It exists, but maybe not how we need it
if (!needDir || c === 'DIR')
return cb(null, c)
if (needDir && c === 'FILE')
return cb()
// otherwise we have to stat, because maybe c=true
// if we know it exists, but not what it is.
}
var exists
var stat = this.statCache[abs]
if (stat !== undefined) {
if (stat === false)
return cb(null, stat)
else {
var type = stat.isDirectory() ? 'DIR' : 'FILE'
if (needDir && type === 'FILE')
return cb()
else
return cb(null, type, stat)
}
}
var self = this
var statcb = inflight('stat\0' + abs, lstatcb_)
if (statcb)
fs.lstat(abs, statcb)
function lstatcb_ (er, lstat) {
if (lstat && lstat.isSymbolicLink()) {
// If it's a symlink, then treat it as the target, unless
// the target does not exist, then treat it as a file.
return fs.stat(abs, function (er, stat) {
if (er)
self._stat2(f, abs, null, lstat, cb)
else
self._stat2(f, abs, er, stat, cb)
})
} else {
self._stat2(f, abs, er, lstat, cb)
}
}
}
Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
if (er) {
this.statCache[abs] = false
return cb()
}
var needDir = f.slice(-1) === '/'
this.statCache[abs] = stat
if (abs.slice(-1) === '/' && !stat.isDirectory())
return cb(null, false, stat)
var c = stat.isDirectory() ? 'DIR' : 'FILE'
this.cache[abs] = this.cache[abs] || c
if (needDir && c !== 'DIR')
return cb()
return cb(null, c, stat)
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | module.exports = globSync
globSync.GlobSync = GlobSync
var fs = require('fs')
var minimatch = require('minimatch')
var Minimatch = minimatch.Minimatch
var Glob = require('./glob.js').Glob
var util = require('util')
var path = require('path')
var assert = require('assert')
var isAbsolute = require('path-is-absolute')
var common = require('./common.js')
var alphasort = common.alphasort
var alphasorti = common.alphasorti
var setopts = common.setopts
var ownProp = common.ownProp
var childrenIgnored = common.childrenIgnored
function globSync (pattern, options) {
if (typeof options === 'function' || arguments.length === 3)
throw new TypeError('callback provided to sync glob\n'+
'See: https://github.com/isaacs/node-glob/issues/167')
return new GlobSync(pattern, options).found
}
function GlobSync (pattern, options) {
if (!pattern)
throw new Error('must provide pattern')
if (typeof options === 'function' || arguments.length === 3)
throw new TypeError('callback provided to sync glob\n'+
'See: https://github.com/isaacs/node-glob/issues/167')
if (!(this instanceof GlobSync))
return new GlobSync(pattern, options)
setopts(this, pattern, options)
if (this.noprocess)
return this
var n = this.minimatch.set.length
this.matches = new Array(n)
for (var i = 0; i < n; i ++) {
this._process(this.minimatch.set[i], i, false)
}
this._finish()
}
GlobSync.prototype._finish = function () {
assert(this instanceof GlobSync)
if (this.realpath) {
var self = this
this.matches.forEach(function (matchset, index) {
var set = self.matches[index] = Object.create(null)
for (var p in matchset) {
try {
p = self._makeAbs(p)
var real = fs.realpathSync(p, self.realpathCache)
set[real] = true
} catch (er) {
if (er.syscall === 'stat')
set[self._makeAbs(p)] = true
else
throw er
}
}
})
}
common.finish(this)
}
GlobSync.prototype._process = function (pattern, index, inGlobStar) {
assert(this instanceof GlobSync)
// Get the first [n] parts of pattern that are all strings.
var n = 0
while (typeof pattern[n] === 'string') {
n ++
}
// now n is the index of the first one that is *not* a string.
// See if there's anything else
var prefix
switch (n) {
// if not, then this is rather simple
case pattern.length:
this._processSimple(pattern.join('/'), index)
return
case 0:
// pattern *starts* with some non-trivial item.
// going to readdir(cwd), but not include the prefix in matches.
prefix = null
break
default:
// pattern has some string bits in the front.
// whatever it starts with, whether that's 'absolute' like /foo/bar,
// or 'relative' like '../baz'
prefix = pattern.slice(0, n).join('/')
break
}
var remain = pattern.slice(n)
// get the list of entries.
var read
if (prefix === null)
read = '.'
else if (isAbsolute(prefix) || isAbsolute(pattern.join('/'))) {
if (!prefix || !isAbsolute(prefix))
prefix = '/' + prefix
read = prefix
} else
read = prefix
var abs = this._makeAbs(read)
//if ignored, skip processing
if (childrenIgnored(this, read))
return
var isGlobStar = remain[0] === minimatch.GLOBSTAR
if (isGlobStar)
this._processGlobStar(prefix, read, abs, remain, index, inGlobStar)
else
this._processReaddir(prefix, read, abs, remain, index, inGlobStar)
}
GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
var entries = this._readdir(abs, inGlobStar)
// if the abs isn't a dir, then nothing can match!
if (!entries)
return
// It will only match dot entries if it starts with a dot, or if
// dot is set. Stuff like @(.foo|.bar) isn't allowed.
var pn = remain[0]
var negate = !!this.minimatch.negate
var rawGlob = pn._glob
var dotOk = this.dot || rawGlob.charAt(0) === '.'
var matchedEntries = []
for (var i = 0; i < entries.length; i++) {
var e = entries[i]
if (e.charAt(0) !== '.' || dotOk) {
var m
if (negate && !prefix) {
m = !e.match(pn)
} else {
m = e.match(pn)
}
if (m)
matchedEntries.push(e)
}
}
var len = matchedEntries.length
// If there are no matched entries, then nothing matches.
if (len === 0)
return
// if this is the last remaining pattern bit, then no need for
// an additional stat *unless* the user has specified mark or
// stat explicitly. We know they exist, since readdir returned
// them.
if (remain.length === 1 && !this.mark && !this.stat) {
if (!this.matches[index])
this.matches[index] = Object.create(null)
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
if (prefix) {
if (prefix.slice(-1) !== '/')
e = prefix + '/' + e
else
e = prefix + e
}
if (e.charAt(0) === '/' && !this.nomount) {
e = path.join(this.root, e)
}
this.matches[index][e] = true
}
// This was the last one, and no stats were needed
return
}
// now test all matched entries as stand-ins for that part
// of the pattern.
remain.shift()
for (var i = 0; i < len; i ++) {
var e = matchedEntries[i]
var newPattern
if (prefix)
newPattern = [prefix, e]
else
newPattern = [e]
this._process(newPattern.concat(remain), index, inGlobStar)
}
}
GlobSync.prototype._emitMatch = function (index, e) {
var abs = this._makeAbs(e)
if (this.mark)
e = this._mark(e)
if (this.matches[index][e])
return
if (this.nodir) {
var c = this.cache[this._makeAbs(e)]
if (c === 'DIR' || Array.isArray(c))
return
}
this.matches[index][e] = true
if (this.stat)
this._stat(e)
}
GlobSync.prototype._readdirInGlobStar = function (abs) {
// follow all symlinked directories forever
// just proceed as if this is a non-globstar situation
if (this.follow)
return this._readdir(abs, false)
var entries
var lstat
var stat
try {
lstat = fs.lstatSync(abs)
} catch (er) {
// lstat failed, doesn't exist
return null
}
var isSym = lstat.isSymbolicLink()
this.symlinks[abs] = isSym
// If it's not a symlink or a dir, then it's definitely a regular file.
// don't bother doing a readdir in that case.
if (!isSym && !lstat.isDirectory())
this.cache[abs] = 'FILE'
else
entries = this._readdir(abs, false)
return entries
}
GlobSync.prototype._readdir = function (abs, inGlobStar) {
var entries
if (inGlobStar && !ownProp(this.symlinks, abs))
return this._readdirInGlobStar(abs)
if (ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (!c || c === 'FILE')
return null
if (Array.isArray(c))
return c
}
try {
return this._readdirEntries(abs, fs.readdirSync(abs))
} catch (er) {
this._readdirError(abs, er)
return null
}
}
GlobSync.prototype._readdirEntries = function (abs, entries) {
// if we haven't asked to stat everything, then just
// assume that everything in there exists, so we can avoid
// having to stat it a second time.
if (!this.mark && !this.stat) {
for (var i = 0; i < entries.length; i ++) {
var e = entries[i]
if (abs === '/')
e = abs + e
else
e = abs + '/' + e
this.cache[e] = true
}
}
this.cache[abs] = entries
// mark and cache dir-ness
return entries
}
GlobSync.prototype._readdirError = function (f, er) {
// handle errors, and cache the information
switch (er.code) {
case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
case 'ENOTDIR': // totally normal. means it *does* exist.
this.cache[this._makeAbs(f)] = 'FILE'
break
case 'ENOENT': // not terribly unusual
case 'ELOOP':
case 'ENAMETOOLONG':
case 'UNKNOWN':
this.cache[this._makeAbs(f)] = false
break
default: // some unusual error. Treat as failure.
this.cache[this._makeAbs(f)] = false
if (this.strict)
throw er
if (!this.silent)
console.error('glob error', er)
break
}
}
GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
var entries = this._readdir(abs, inGlobStar)
// no entries means not a dir, so it can never have matches
// foo.txt/** doesn't match foo.txt
if (!entries)
return
// test without the globstar, and with every child both below
// and replacing the globstar.
var remainWithoutGlobStar = remain.slice(1)
var gspref = prefix ? [ prefix ] : []
var noGlobStar = gspref.concat(remainWithoutGlobStar)
// the noGlobStar pattern exits the inGlobStar state
this._process(noGlobStar, index, false)
var len = entries.length
var isSym = this.symlinks[abs]
// If it's a symlink, and we're in a globstar, then stop
if (isSym && inGlobStar)
return
for (var i = 0; i < len; i++) {
var e = entries[i]
if (e.charAt(0) === '.' && !this.dot)
continue
// these two cases enter the inGlobStar state
var instead = gspref.concat(entries[i], remainWithoutGlobStar)
this._process(instead, index, true)
var below = gspref.concat(entries[i], remain)
this._process(below, index, true)
}
}
GlobSync.prototype._processSimple = function (prefix, index) {
// XXX review this. Shouldn't it be doing the mounting etc
// before doing stat? kinda weird?
var exists = this._stat(prefix)
if (!this.matches[index])
this.matches[index] = Object.create(null)
// If it doesn't exist, then just mark the lack of results
if (!exists)
return
if (prefix && isAbsolute(prefix) && !this.nomount) {
var trail = /[\/\\]$/.test(prefix)
if (prefix.charAt(0) === '/') {
prefix = path.join(this.root, prefix)
} else {
prefix = path.resolve(this.root, prefix)
if (trail)
prefix += '/'
}
}
if (process.platform === 'win32')
prefix = prefix.replace(/\\/g, '/')
// Mark this as a match
this.matches[index][prefix] = true
}
// Returns either 'DIR', 'FILE', or false
GlobSync.prototype._stat = function (f) {
var abs = this._makeAbs(f)
var needDir = f.slice(-1) === '/'
if (f.length > this.maxLength)
return false
if (!this.stat && ownProp(this.cache, abs)) {
var c = this.cache[abs]
if (Array.isArray(c))
c = 'DIR'
// It exists, but maybe not how we need it
if (!needDir || c === 'DIR')
return c
if (needDir && c === 'FILE')
return false
// otherwise we have to stat, because maybe c=true
// if we know it exists, but not what it is.
}
var exists
var stat = this.statCache[abs]
if (!stat) {
var lstat
try {
lstat = fs.lstatSync(abs)
} catch (er) {
return false
}
if (lstat.isSymbolicLink()) {
try {
stat = fs.statSync(abs)
} catch (er) {
stat = lstat
}
} else {
stat = lstat
}
}
this.statCache[abs] = stat
var c = stat.isDirectory() ? 'DIR' : 'FILE'
this.cache[abs] = this.cache[abs] || c
if (needDir && c !== 'DIR')
return false
return c
}
GlobSync.prototype._mark = function (p) {
return common.mark(this, p)
}
GlobSync.prototype._makeAbs = function (f) {
return common.makeAbs(this, f)
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| inflight.js | 25% | (7 / 28) | 0% | (0 / 4) | 0% | (0 / 5) | 25.93% | (7 / 27) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 1 1 1 1 1 1 1 | var wrappy = require('wrappy')
var reqs = Object.create(null)
var once = require('once')
module.exports = wrappy(inflight)
function inflight (key, cb) {
if (reqs[key]) {
reqs[key].push(cb)
return null
} else {
reqs[key] = [cb]
return makeres(key)
}
}
function makeres (key) {
return once(function RES () {
var cbs = reqs[key]
var len = cbs.length
var args = slice(arguments)
for (var i = 0; i < len; i++) {
cbs[i].apply(null, args)
}
if (cbs.length > len) {
// added more in the interim.
// de-zalgo, just in case, but don't call again.
cbs.splice(0, len)
process.nextTick(function () {
RES.apply(null, args)
})
} else {
delete reqs[key]
}
})
}
function slice (args) {
var length = args.length
var array = []
for (var i = 0; i < length; i++) array[i] = args[i]
return array
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| wrappy.js | 36.84% | (7 / 19) | 40% | (4 / 10) | 25% | (1 / 4) | 38.89% | (7 / 18) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 1 1 1 1 1 1 1 | // Returns a wrapper function that returns a wrapped callback
// The wrapper function should do some stuff, and return a
// presumably different callback function.
// This makes sure that own properties are retained, so that
// decorations and such are not lost along the way.
module.exports = wrappy
function wrappy (fn, cb) {
Iif (fn && cb) return wrappy(fn)(cb)
Iif (typeof fn !== 'function')
throw new TypeError('need wrapper function')
Object.keys(fn).forEach(function (k) {
wrapper[k] = fn[k]
})
return wrapper
function wrapper() {
var args = new Array(arguments.length)
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i]
}
var ret = fn.apply(this, args)
var cb = args[args.length-1]
if (typeof ret === 'function' && ret !== cb) {
Object.keys(cb).forEach(function (k) {
ret[k] = cb[k]
})
}
return ret
}
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| inherits.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) |
| 1 2 3 | 1 | module.exports = require('util').inherits
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| minimatch.js | 10.49% | (45 / 429) | 0% | (0 / 261) | 5.88% | (2 / 34) | 11.11% | (45 / 405) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 14 14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | module.exports = minimatch
minimatch.Minimatch = Minimatch
var path = { sep: '/' }
try {
path = require('path')
} catch (er) {}
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = require('brace-expansion')
// any single thing other than /
// don't need to escape / when using new RegExp()
var qmark = '[^/]'
// * => any number of characters
var star = qmark + '*?'
// ** when dots are allowed. Anything goes, except .. and .
// not (^ or / followed by one or two dots followed by $ or /),
// followed by anything, any number of times.
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
// not a ^ or / followed by a dot,
// followed by anything, any number of times.
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
// characters that need to be escaped in RegExp.
var reSpecials = charSet('().*{}+?[]^$\\!')
// "abc" -> { a:true, b:true, c:true }
function charSet (s) {
return s.split('').reduce(function (set, c) {
set[c] = true
return set
}, {})
}
// normalizes slashes.
var slashSplit = /\/+/
minimatch.filter = filter
function filter (pattern, options) {
options = options || {}
return function (p, i, list) {
return minimatch(p, pattern, options)
}
}
function ext (a, b) {
a = a || {}
b = b || {}
var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) {
t[k] = a[k]
})
return t
}
minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch
var orig = minimatch
var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options))
}
m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options))
}
return m
}
Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch
}
function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
if (!options) options = {}
// shortcut: comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
return false
}
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p)
}
function Minimatch (pattern, options) {
if (!(this instanceof Minimatch)) {
return new Minimatch(pattern, options)
}
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
if (!options) options = {}
pattern = pattern.trim()
// windows support: need to use /, not \
if (path.sep !== '/') {
pattern = pattern.split(path.sep).join('/')
}
this.options = options
this.set = []
this.pattern = pattern
this.regexp = null
this.negate = false
this.comment = false
this.empty = false
// make the set of regexps etc.
this.make()
}
Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make
function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern
var options = this.options
// empty patterns and comments match nothing.
if (!options.nocomment && pattern.charAt(0) === '#') {
this.comment = true
return
}
if (!pattern) {
this.empty = true
return
}
// step 1: figure out negation, etc.
this.parseNegate()
// step 2: expand braces
var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = console.error
this.debug(this.pattern, set)
// step 3: now we have a set, so turn each one into a series of path-portion
// matching patterns.
// These will be regexps, except in the case of "**", which is
// set to the GLOBSTAR object for globstar behavior,
// and will not contain any / characters
set = this.globParts = set.map(function (s) {
return s.split(slashSplit)
})
this.debug(this.pattern, set)
// glob --> regexps
set = set.map(function (s, si, set) {
return s.map(this.parse, this)
}, this)
this.debug(this.pattern, set)
// filter out everything that didn't compile properly.
set = set.filter(function (s) {
return s.indexOf(false) === -1
})
this.debug(this.pattern, set)
this.set = set
}
Minimatch.prototype.parseNegate = parseNegate
function parseNegate () {
var pattern = this.pattern
var negate = false
var options = this.options
var negateOffset = 0
if (options.nonegate) return
for (var i = 0, l = pattern.length
; i < l && pattern.charAt(i) === '!'
; i++) {
negate = !negate
negateOffset++
}
if (negateOffset) this.pattern = pattern.substr(negateOffset)
this.negate = negate
}
// Brace expansion:
// a{b,c}d -> abd acd
// a{b,}c -> abc ac
// a{0..3}d -> a0d a1d a2d a3d
// a{b,c{d,e}f}g -> abg acdfg acefg
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
//
// Invalid sets are not expanded.
// a{2..}b -> a{2..}b
// a{b}c -> a{b}c
minimatch.braceExpand = function (pattern, options) {
return braceExpand(pattern, options)
}
Minimatch.prototype.braceExpand = braceExpand
function braceExpand (pattern, options) {
if (!options) {
if (this instanceof Minimatch) {
options = this.options
} else {
options = {}
}
}
pattern = typeof pattern === 'undefined'
? this.pattern : pattern
if (typeof pattern === 'undefined') {
throw new Error('undefined pattern')
}
if (options.nobrace ||
!pattern.match(/\{.*\}/)) {
// shortcut. no need to expand.
return [pattern]
}
return expand(pattern)
}
// parse a component of the expanded set.
// At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full
// pattern, split on '/', and then turned into a regular expression.
// A regexp is made at the end which joins each array with an
// escaped /, and another full one which joins each regexp with |.
//
// Following the lead of Bash 4.1, note that "**" only has special meaning
// when it is the *only* thing in a path portion. Otherwise, any series
// of * is equivalent to a single *. Globstar behavior is enabled by
// default, and can be disabled by setting options.noglobstar.
Minimatch.prototype.parse = parse
var SUBPARSE = {}
function parse (pattern, isSub) {
var options = this.options
// shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR
if (pattern === '') return ''
var re = ''
var hasMagic = !!options.nocase
var escaping = false
// ? => one single character
var patternListStack = []
var negativeLists = []
var plType
var stateChar
var inClass = false
var reClassStart = -1
var classStart = -1
// . and .. never match anything that doesn't start with .,
// even when options.dot is set.
var patternStart = pattern.charAt(0) === '.' ? '' // anything
// not (start or / followed by . or .. followed by / or end)
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
: '(?!\\.)'
var self = this
function clearStateChar () {
if (stateChar) {
// we had some state-tracking character
// that wasn't consumed by this pass.
switch (stateChar) {
case '*':
re += star
hasMagic = true
break
case '?':
re += qmark
hasMagic = true
break
default:
re += '\\' + stateChar
break
}
self.debug('clearStateChar %j %j', stateChar, re)
stateChar = false
}
}
for (var i = 0, len = pattern.length, c
; (i < len) && (c = pattern.charAt(i))
; i++) {
this.debug('%s\t%s %s %j', pattern, i, re, c)
// skip over any that are escaped.
if (escaping && reSpecials[c]) {
re += '\\' + c
escaping = false
continue
}
switch (c) {
case '/':
// completely not allowed, even escaped.
// Should already be path-split by now.
return false
case '\\':
clearStateChar()
escaping = true
continue
// the various stateChar values
// for the "extglob" stuff.
case '?':
case '*':
case '+':
case '@':
case '!':
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
// all of those are literals inside a class, except that
// the glob [!a] means [^a] in regexp
if (inClass) {
this.debug(' in class')
if (c === '!' && i === classStart + 1) c = '^'
re += c
continue
}
// if we already have a stateChar, then it means
// that there was something like ** or +? in there.
// Handle the stateChar, then proceed with this one.
self.debug('call clearStateChar %j', stateChar)
clearStateChar()
stateChar = c
// if extglob is disabled, then +(asdf|foo) isn't a thing.
// just clear the statechar *now*, rather than even diving into
// the patternList stuff.
if (options.noext) clearStateChar()
continue
case '(':
if (inClass) {
re += '('
continue
}
if (!stateChar) {
re += '\\('
continue
}
plType = stateChar
patternListStack.push({
type: plType,
start: i - 1,
reStart: re.length
})
// negation is (?:(?!js)[^/]*)
re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
this.debug('plType %j %j', stateChar, re)
stateChar = false
continue
case ')':
if (inClass || !patternListStack.length) {
re += '\\)'
continue
}
clearStateChar()
hasMagic = true
re += ')'
var pl = patternListStack.pop()
plType = pl.type
// negation is (?:(?!js)[^/]*)
// The others are (?:<pattern>)<type>
switch (plType) {
case '!':
negativeLists.push(pl)
re += ')[^/]*?)'
pl.reEnd = re.length
break
case '?':
case '+':
case '*':
re += plType
break
case '@': break // the default anyway
}
continue
case '|':
if (inClass || !patternListStack.length || escaping) {
re += '\\|'
escaping = false
continue
}
clearStateChar()
re += '|'
continue
// these are mostly the same in regexp and glob
case '[':
// swallow any state-tracking char before the [
clearStateChar()
if (inClass) {
re += '\\' + c
continue
}
inClass = true
classStart = i
reClassStart = re.length
re += c
continue
case ']':
// a right bracket shall lose its special
// meaning and represent itself in
// a bracket expression if it occurs
// first in the list. -- POSIX.2 2.8.3.2
if (i === classStart + 1 || !inClass) {
re += '\\' + c
escaping = false
continue
}
// handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
}
// finish up the class.
hasMagic = true
inClass = false
re += c
continue
default:
// swallow any state char that wasn't consumed
clearStateChar()
if (escaping) {
// no need
escaping = false
} else if (reSpecials[c]
&& !(c === '^' && inClass)) {
re += '\\'
}
re += c
} // switch
} // for
// handle the case where we left a class open.
// "[abc" is valid, equivalent to "\[abc"
if (inClass) {
// split where the last [ was, and escape it
// this is a huge pita. We now have to re-walk
// the contents of the would-be class to re-translate
// any characters that were passed through as-is
cs = pattern.substr(classStart + 1)
sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0]
hasMagic = hasMagic || sp[1]
}
// handle the case where we had a +( thing at the *end*
// of the pattern.
// each pattern list stack adds 3 chars, and we need to go through
// and escape any | chars that were passed through as-is for the regexp.
// Go through and escape them, taking care not to double-escape any
// | chars that were already escaped.
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
var tail = re.slice(pl.reStart + 3)
// maybe some even number of \, then maybe 1 \, followed by a |
tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) {
if (!$2) {
// the | isn't already escaped, so escape it.
$2 = '\\'
}
// need to escape all those slashes *again*, without escaping the
// one that we need for escaping the | character. As it works out,
// escaping an even number of slashes can be done by simply repeating
// it exactly after itself. That's why this trick works.
//
// I am sorry that you have to see this.
return $1 + $1 + $2 + '|'
})
this.debug('tail=%j\n %s', tail, tail)
var t = pl.type === '*' ? star
: pl.type === '?' ? qmark
: '\\' + pl.type
hasMagic = true
re = re.slice(0, pl.reStart) + t + '\\(' + tail
}
// handle trailing things that only matter at the very end.
clearStateChar()
if (escaping) {
// trailing \\
re += '\\\\'
}
// only need to apply the nodot start if the re starts with
// something that could conceivably capture a dot
var addPatternStart = false
switch (re.charAt(0)) {
case '.':
case '[':
case '(': addPatternStart = true
}
// Hack to work around lack of negative lookbehind in JS
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
// like 'a.xyz.yz' doesn't match. So, the first negative
// lookahead, has to look ALL the way ahead, to the end of
// the pattern.
for (var n = negativeLists.length - 1; n > -1; n--) {
var nl = negativeLists[n]
var nlBefore = re.slice(0, nl.reStart)
var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
var nlAfter = re.slice(nl.reEnd)
nlLast += nlAfter
// Handle nested stuff like *(*.js|!(*.json)), where open parens
// mean that we should *not* include the ) in the bit that is considered
// "after" the negated section.
var openParensBefore = nlBefore.split('(').length - 1
var cleanAfter = nlAfter
for (i = 0; i < openParensBefore; i++) {
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
}
nlAfter = cleanAfter
var dollar = ''
if (nlAfter === '' && isSub !== SUBPARSE) {
dollar = '$'
}
var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
re = newRe
}
// if the re is not "" at this point, then we need to make sure
// it doesn't match against an empty path part.
// Otherwise a/* will match a/, which it should not.
if (re !== '' && hasMagic) {
re = '(?=.)' + re
}
if (addPatternStart) {
re = patternStart + re
}
// parsing just a piece of a larger pattern.
if (isSub === SUBPARSE) {
return [re, hasMagic]
}
// skip the regexp for non-magical patterns
// unescape anything in it, though, so that it'll be
// an exact match against a file etc.
if (!hasMagic) {
return globUnescape(pattern)
}
var flags = options.nocase ? 'i' : ''
var regExp = new RegExp('^' + re + '$', flags)
regExp._glob = pattern
regExp._src = re
return regExp
}
minimatch.makeRe = function (pattern, options) {
return new Minimatch(pattern, options || {}).makeRe()
}
Minimatch.prototype.makeRe = makeRe
function makeRe () {
if (this.regexp || this.regexp === false) return this.regexp
// at this point, this.set is a 2d array of partial
// pattern strings, or "**".
//
// It's better to use .match(). This function shouldn't
// be used, really, but it's pretty convenient sometimes,
// when you just want to work with a regex.
var set = this.set
if (!set.length) {
this.regexp = false
return this.regexp
}
var options = this.options
var twoStar = options.noglobstar ? star
: options.dot ? twoStarDot
: twoStarNoDot
var flags = options.nocase ? 'i' : ''
var re = set.map(function (pattern) {
return pattern.map(function (p) {
return (p === GLOBSTAR) ? twoStar
: (typeof p === 'string') ? regExpEscape(p)
: p._src
}).join('\\\/')
}).join('|')
// must match entire pattern
// ending in a * or ** will make it less strict.
re = '^(?:' + re + ')$'
// can match anything, as long as it's not this.
if (this.negate) re = '^(?!' + re + ').*$'
try {
this.regexp = new RegExp(re, flags)
} catch (ex) {
this.regexp = false
}
return this.regexp
}
minimatch.match = function (list, pattern, options) {
options = options || {}
var mm = new Minimatch(pattern, options)
list = list.filter(function (f) {
return mm.match(f)
})
if (mm.options.nonull && !list.length) {
list.push(pattern)
}
return list
}
Minimatch.prototype.match = match
function match (f, partial) {
this.debug('match', f, this.pattern)
// short-circuit in the case of busted things.
// comments, etc.
if (this.comment) return false
if (this.empty) return f === ''
if (f === '/' && partial) return true
var options = this.options
// windows: need to use /, not \
if (path.sep !== '/') {
f = f.split(path.sep).join('/')
}
// treat the test path as a set of pathparts.
f = f.split(slashSplit)
this.debug(this.pattern, 'split', f)
// just ONE of the pattern sets in this.set needs to match
// in order for it to be valid. If negating, then just one
// match means that we have failed.
// Either way, return on the first hit.
var set = this.set
this.debug(this.pattern, 'set', set)
// Find the basename of the path by looking for the last non-empty segment
var filename
var i
for (i = f.length - 1; i >= 0; i--) {
filename = f[i]
if (filename) break
}
for (i = 0; i < set.length; i++) {
var pattern = set[i]
var file = f
if (options.matchBase && pattern.length === 1) {
file = [filename]
}
var hit = this.matchOne(file, pattern, partial)
if (hit) {
if (options.flipNegate) return true
return !this.negate
}
}
// didn't get any hits. this is success if it's a negative
// pattern, failure otherwise.
if (options.flipNegate) return false
return this.negate
}
// set partial to true to test if, for example,
// "/a/b" matches the start of "/*/b/*/d"
// Partial means, if you run out of file before you run
// out of pattern, then that's fine, as long as all
// the parts match.
Minimatch.prototype.matchOne = function (file, pattern, partial) {
var options = this.options
this.debug('matchOne',
{ 'this': this, file: file, pattern: pattern })
this.debug('matchOne', file.length, pattern.length)
for (var fi = 0,
pi = 0,
fl = file.length,
pl = pattern.length
; (fi < fl) && (pi < pl)
; fi++, pi++) {
this.debug('matchOne loop')
var p = pattern[pi]
var f = file[fi]
this.debug(pattern, p, f)
// should be impossible.
// some invalid regexp stuff in the set.
if (p === false) return false
if (p === GLOBSTAR) {
this.debug('GLOBSTAR', [pattern, p, f])
// "**"
// a/**/b/**/c would match the following:
// a/b/x/y/z/c
// a/x/y/z/b/c
// a/b/x/b/x/c
// a/b/c
// To do this, take the rest of the pattern after
// the **, and see if it would match the file remainder.
// If so, return success.
// If not, the ** "swallows" a segment, and try again.
// This is recursively awful.
//
// a/**/b/**/c matching a/b/x/y/z/c
// - a matches a
// - doublestar
// - matchOne(b/x/y/z/c, b/**/c)
// - b matches b
// - doublestar
// - matchOne(x/y/z/c, c) -> no
// - matchOne(y/z/c, c) -> no
// - matchOne(z/c, c) -> no
// - matchOne(c, c) yes, hit
var fr = fi
var pr = pi + 1
if (pr === pl) {
this.debug('** at the end')
// a ** at the end will just swallow the rest.
// We have found a match.
// however, it will not swallow /.x, unless
// options.dot is set.
// . and .. are *never* matched by **, for explosively
// exponential reasons.
for (; fi < fl; fi++) {
if (file[fi] === '.' || file[fi] === '..' ||
(!options.dot && file[fi].charAt(0) === '.')) return false
}
return true
}
// ok, let's see if we can swallow whatever we can.
while (fr < fl) {
var swallowee = file[fr]
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
// XXX remove this slice. Just pass the start index.
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
this.debug('globstar found match!', fr, fl, swallowee)
// found a match.
return true
} else {
// can't swallow "." or ".." ever.
// can only swallow ".foo" when explicitly asked.
if (swallowee === '.' || swallowee === '..' ||
(!options.dot && swallowee.charAt(0) === '.')) {
this.debug('dot detected!', file, fr, pattern, pr)
break
}
// ** swallows a segment, and continue.
this.debug('globstar swallow a segment, and continue')
fr++
}
}
// no match was found.
// However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then
if (partial) {
// ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
if (fr === fl) return true
}
return false
}
// something other than **
// non-magic patterns just have to match exactly
// patterns with magic have been turned into regexps.
var hit
if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p
}
this.debug('string match', p, f, hit)
} else {
hit = f.match(p)
this.debug('pattern match', p, f, hit)
}
if (!hit) return false
}
// Note: ending in / means that we'll get a final ""
// at the end of the pattern. This can only match a
// corresponding "" at the end of the file.
// If the file ends in /, then it can only match a
// a pattern that ends in /, unless the pattern just
// doesn't have any more for it. But, a/b/ should *not*
// match "a/b/*", even though "" matches against the
// [^/]*? pattern, except in partial mode, where it might
// simply not be reached yet.
// However, a/b/ should still satisfy a/*
// now either we fell off the end of the pattern, or we're done.
if (fi === fl && pi === pl) {
// ran out of pattern and filename at the same time.
// an exact hit!
return true
} else if (fi === fl) {
// ran out of file, but still had pattern left.
// this is ok if we're doing the match as part of
// a glob fs traversal.
return partial
} else if (pi === pl) {
// ran out of pattern, still have file left.
// this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash.
// a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
}
// should be unreachable.
throw new Error('wtf?')
}
// replace stuff like \* with *
function globUnescape (s) {
return s.replace(/\\(.)/g, '$1')
}
function regExpEscape (s) {
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| index.js | 17.59% | (19 / 108) | 0% | (0 / 53) | 0% | (0 / 13) | 17.92% | (19 / 106) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | var concatMap = require('concat-map');
var balanced = require('balanced-match');
module.exports = expandTop;
var escSlash = '\0SLASH'+Math.random()+'\0';
var escOpen = '\0OPEN'+Math.random()+'\0';
var escClose = '\0CLOSE'+Math.random()+'\0';
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
: str.charCodeAt(0);
}
function escapeBraces(str) {
return str.split('\\\\').join(escSlash)
.split('\\{').join(escOpen)
.split('\\}').join(escClose)
.split('\\,').join(escComma)
.split('\\.').join(escPeriod);
}
function unescapeBraces(str) {
return str.split(escSlash).join('\\')
.split(escOpen).join('{')
.split(escClose).join('}')
.split(escComma).join(',')
.split(escPeriod).join('.');
}
// Basically just str.split(","), but handling cases
// where we have nested braced sections, which should be
// treated as individual members, like {a,{b,c},d}
function parseCommaParts(str) {
if (!str)
return [''];
var parts = [];
var m = balanced('{', '}', str);
if (!m)
return str.split(',');
var pre = m.pre;
var body = m.body;
var post = m.post;
var p = pre.split(',');
p[p.length-1] += '{' + body + '}';
var postParts = parseCommaParts(post);
if (post.length) {
p[p.length-1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expandTop(str) {
if (!str)
return [];
return expand(escapeBraces(str), true).map(unescapeBraces);
}
function identity(e) {
return e;
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand(str, isTop) {
var expansions = [];
var m = balanced('{', '}', str);
if (!m || /\$$/.test(m.pre)) return [str];
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
var isOptions = /^(.*,)+(.+)?$/.test(m.body);
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,.*}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand(str);
}
return [str];
}
var n;
if (isSequence) {
n = m.body.split(/\.\./);
} else {
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand(n[0], false).map(embrace);
if (n.length === 1) {
var post = m.post.length
? expand(m.post, false)
: [''];
return post.map(function(p) {
return m.pre + n[0] + p;
});
}
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
? expand(m.post, false)
: [''];
var N;
if (isSequence) {
var x = numeric(n[0]);
var y = numeric(n[1]);
var width = Math.max(n[0].length, n[1].length)
var incr = n.length == 3
? Math.abs(numeric(n[2]))
: 1;
var test = lte;
var reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
var pad = n.some(isPadded);
N = [];
for (var i = x; test(i, y); i += incr) {
var c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\')
c = '';
} else {
c = String(i);
if (pad) {
var need = width - c.length;
if (need > 0) {
var z = new Array(need + 1).join('0');
if (i < 0)
c = '-' + z + c.slice(1);
else
c = z + c;
}
}
}
N.push(c);
}
} else {
N = concatMap(n, function(el) { return expand(el, false) });
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);
}
}
return expansions;
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| index.js | 7.41% | (2 / 27) | 0% | (0 / 18) | 0% | (0 / 1) | 7.69% | (2 / 26) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 1 1 | module.exports = balanced; function balanced(a, b, str) { var bal = 0; var m = {}; var ended = false; for (var i = 0; i < str.length; i++) { if (a == str.substr(i, a.length)) { if (!('start' in m)) m.start = i; bal++; } else if (b == str.substr(i, b.length) && 'start' in m) { ended = true; bal--; if (!bal) { m.end = i; m.pre = str.substr(0, m.start); m.body = (m.end - m.start > 1) ? str.substring(m.start + a.length, m.end) : ''; m.post = str.slice(m.end + b.length); return m; } } } // if we opened more than we closed, find the one we closed if (bal && ended) { var start = m.start + a.length; m = balanced(a, b, str.substr(start)); if (m) { m.start += start; m.end += start; m.pre = str.slice(0, start) + m.pre; } return m; } } |
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| index.js | 20% | (2 / 10) | 25% | (1 / 4) | 0% | (0 / 2) | 22.22% | (2 / 9) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 1 1 | module.exports = function (xs, fn) { var res = []; for (var i = 0; i < xs.length; i++) { var x = fn(xs[i], i); if (isArray(x)) res.push.apply(res, x); else res.push(x); } return res; }; var isArray = Array.isArray || function (xs) { return Object.prototype.toString.call(xs) === '[object Array]'; }; |
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| once.js | 53.85% | (7 / 13) | 0% | (0 / 2) | 25% | (1 / 4) | 58.33% | (7 / 12) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 1 1 1 1 1 1 1 | var wrappy = require('wrappy')
module.exports = wrappy(once)
once.proto = once(function () {
Object.defineProperty(Function.prototype, 'once', {
value: function () {
return once(this)
},
configurable: true
})
})
function once (fn) {
var f = function () {
if (f.called) return f.value
f.called = true
return f.value = fn.apply(this, arguments)
}
f.called = false
return f
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| wrappy.js | 36.84% | (7 / 19) | 40% | (4 / 10) | 25% | (1 / 4) | 38.89% | (7 / 18) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 1 1 1 1 1 1 1 | // Returns a wrapper function that returns a wrapped callback
// The wrapper function should do some stuff, and return a
// presumably different callback function.
// This makes sure that own properties are retained, so that
// decorations and such are not lost along the way.
module.exports = wrappy
function wrappy (fn, cb) {
Iif (fn && cb) return wrappy(fn)(cb)
Iif (typeof fn !== 'function')
throw new TypeError('need wrapper function')
Object.keys(fn).forEach(function (k) {
wrapper[k] = fn[k]
})
return wrapper
function wrapper() {
var args = new Array(arguments.length)
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i]
}
var ret = fn.apply(this, args)
var cb = args[args.length-1]
if (typeof ret === 'function' && ret !== cb) {
Object.keys(cb).forEach(function (k) {
ret[k] = cb[k]
})
}
return ret
}
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| index.js | 45.45% | (5 / 11) | 12.5% | (1 / 8) | 0% | (0 / 2) | 45.45% | (5 / 11) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 1 1 1 1 1 | 'use strict'; function posix(path) { return path.charAt(0) === '/'; }; function win32(path) { // https://github.com/joyent/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56 var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; var result = splitDeviceRe.exec(path); var device = result[1] || ''; var isUnc = !!device && device.charAt(1) !== ':'; // UNC paths are always absolute return !!result[2] || isUnc; }; module.exports = process.platform === 'win32' ? win32 : posix; module.exports.posix = posix; module.exports.win32 = win32; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | 1 1 1 1 1 1 1 1 1 |
/**
* Module dependencies.
*/
var base64 = require('base64-js');
var xmlbuilder = require('xmlbuilder');
/**
* Module exports.
*/
exports.build = build;
/**
* Accepts a `Date` instance and returns an ISO date string.
*
* @param {Date} d - Date instance to serialize
* @returns {String} ISO date string representation of `d`
* @api private
*/
function ISODateString(d){
function pad(n){
return n < 10 ? '0' + n : n;
}
return d.getUTCFullYear()+'-'
+ pad(d.getUTCMonth()+1)+'-'
+ pad(d.getUTCDate())+'T'
+ pad(d.getUTCHours())+':'
+ pad(d.getUTCMinutes())+':'
+ pad(d.getUTCSeconds())+'Z';
}
/**
* Returns the internal "type" of `obj` via the
* `Object.prototype.toString()` trick.
*
* @param {Mixed} obj - any value
* @returns {String} the internal "type" name
* @api private
*/
var toString = Object.prototype.toString;
function type (obj) {
var m = toString.call(obj).match(/\[object (.*)\]/);
return m ? m[1] : m;
}
/**
* Generate an XML plist string from the input object `obj`.
*
* @param {Object} obj - the object to convert
* @param {Object} [opts] - optional options object
* @returns {String} converted plist XML string
* @api public
*/
function build (obj, opts) {
var XMLHDR = {
version: '1.0',
encoding: 'UTF-8'
};
var XMLDTD = {
pubid: '-//Apple//DTD PLIST 1.0//EN',
sysid: 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'
};
var doc = xmlbuilder.create('plist');
doc.dec(XMLHDR.version, XMLHDR.encoding, XMLHDR.standalone);
doc.dtd(XMLDTD.pubid, XMLDTD.sysid);
doc.att('version', '1.0');
walk_obj(obj, doc);
if (!opts) opts = {};
// default `pretty` to `true`
opts.pretty = opts.pretty !== false;
return doc.end(opts);
}
/**
* depth first, recursive traversal of a javascript object. when complete,
* next_child contains a reference to the build XML object.
*
* @api private
*/
function walk_obj(next, next_child) {
var tag_type, i, prop;
var name = type(next);
if (Array.isArray(next)) {
next_child = next_child.ele('array');
for (i = 0; i < next.length; i++) {
walk_obj(next[i], next_child);
}
} else if (Buffer.isBuffer(next)) {
next_child.ele('data').raw(next.toString('base64'));
} else if ('Object' == name) {
next_child = next_child.ele('dict');
for (prop in next) {
if (next.hasOwnProperty(prop)) {
next_child.ele('key').txt(prop);
walk_obj(next[prop], next_child);
}
}
} else if ('Number' == name) {
// detect if this is an integer or real
// TODO: add an ability to force one way or another via a "cast"
tag_type = (next % 1 === 0) ? 'integer' : 'real';
next_child.ele(tag_type).txt(next.toString());
} else if ('Date' == name) {
next_child.ele('date').txt(ISODateString(new Date(next)));
} else if ('Boolean' == name) {
next_child.ele(next ? 'true' : 'false');
} else if ('String' == name) {
next_child.ele('string').txt(next);
} else if ('ArrayBuffer' == name) {
next_child.ele('data').raw(base64.fromByteArray(next));
} else if (next.buffer && 'ArrayBuffer' == type(next.buffer)) {
// a typed array
next_child.ele('data').raw(base64.fromByteArray(new Uint8Array(next.buffer), next_child));
}
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 1 1 1 1 1 1 1 1 | /**
* Module dependencies.
*/
var fs = require('fs');
var parse = require('./parse');
var deprecate = require('util-deprecate');
/**
* Module exports.
*/
exports.parseFile = deprecate(parseFile, '`parseFile()` is deprecated. ' +
'Use `parseString()` instead.');
exports.parseFileSync = deprecate(parseFileSync, '`parseFileSync()` is deprecated. ' +
'Use `parseStringSync()` instead.');
/**
* Parses file `filename` as a .plist file.
* Invokes `fn` callback function when done.
*
* @param {String} filename - name of the file to read
* @param {Function} fn - callback function
* @api public
* @deprecated use parseString() instead
*/
function parseFile (filename, fn) {
fs.readFile(filename, { encoding: 'utf8' }, onread);
function onread (err, inxml) {
if (err) return fn(err);
parse.parseString(inxml, fn);
}
}
/**
* Parses file `filename` as a .plist file.
* Returns a when done.
*
* @param {String} filename - name of the file to read
* @param {Function} fn - callback function
* @api public
* @deprecated use parseStringSync() instead
*/
function parseFileSync (filename) {
var inxml = fs.readFileSync(filename, 'utf8');
return parse.parseStringSync(inxml);
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | 1 1 1 1 1 1 1 1 1 1 |
/**
* Module dependencies.
*/
var deprecate = require('util-deprecate');
var DOMParser = require('xmldom').DOMParser;
/**
* Module exports.
*/
exports.parse = parse;
exports.parseString = deprecate(parseString, '`parseString()` is deprecated. ' +
'It\'s not actually async. Use `parse()` instead.');
exports.parseStringSync = deprecate(parseStringSync, '`parseStringSync()` is ' +
'deprecated. Use `parse()` instead.');
/**
* We ignore raw text (usually whitespace), <!-- xml comments -->,
* and raw CDATA nodes.
*
* @param {Element} node
* @returns {Boolean}
* @api private
*/
function shouldIgnoreNode (node) {
return node.nodeType === 3 // text
|| node.nodeType === 8 // comment
|| node.nodeType === 4; // cdata
}
/**
* Parses a Plist XML string. Returns an Object.
*
* @param {String} xml - the XML String to decode
* @returns {Mixed} the decoded value from the Plist XML
* @api public
*/
function parse (xml) {
var doc = new DOMParser().parseFromString(xml);
if (doc.documentElement.nodeName !== 'plist') {
throw new Error('malformed document. First element should be <plist>');
}
var plist = parsePlistXML(doc.documentElement);
// the root <plist> node gets interpreted as an Array,
// so pull out the inner data first
if (plist.length == 1) plist = plist[0];
return plist;
}
/**
* Parses a Plist XML string. Returns an Object. Takes a `callback` function.
*
* @param {String} xml - the XML String to decode
* @param {Function} callback - callback function
* @returns {Mixed} the decoded value from the Plist XML
* @api public
* @deprecated not actually async. use parse() instead
*/
function parseString (xml, callback) {
var doc, error, plist;
try {
doc = new DOMParser().parseFromString(xml);
plist = parsePlistXML(doc.documentElement);
} catch(e) {
error = e;
}
callback(error, plist);
}
/**
* Parses a Plist XML string. Returns an Object.
*
* @param {String} xml - the XML String to decode
* @param {Function} callback - callback function
* @returns {Mixed} the decoded value from the Plist XML
* @api public
* @deprecated use parse() instead
*/
function parseStringSync (xml) {
var doc = new DOMParser().parseFromString(xml);
var plist;
if (doc.documentElement.nodeName !== 'plist') {
throw new Error('malformed document. First element should be <plist>');
}
plist = parsePlistXML(doc.documentElement);
// if the plist is an array with 1 element, pull it out of the array
if (plist.length == 1) {
plist = plist[0];
}
return plist;
}
/**
* Convert an XML based plist document into a JSON representation.
*
* @param {Object} xml_node - current XML node in the plist
* @returns {Mixed} built up JSON object
* @api private
*/
function parsePlistXML (node) {
var i, new_obj, key, val, new_arr, res, d;
if (!node)
return null;
if (node.nodeName === 'plist') {
new_arr = [];
for (i=0; i < node.childNodes.length; i++) {
// ignore comment nodes (text)
if (!shouldIgnoreNode(node.childNodes[i])) {
new_arr.push( parsePlistXML(node.childNodes[i]));
}
}
return new_arr;
} else if (node.nodeName === 'dict') {
new_obj = {};
key = null;
for (i=0; i < node.childNodes.length; i++) {
// ignore comment nodes (text)
if (!shouldIgnoreNode(node.childNodes[i])) {
if (key === null) {
key = parsePlistXML(node.childNodes[i]);
} else {
new_obj[key] = parsePlistXML(node.childNodes[i]);
key = null;
}
}
}
return new_obj;
} else if (node.nodeName === 'array') {
new_arr = [];
for (i=0; i < node.childNodes.length; i++) {
// ignore comment nodes (text)
if (!shouldIgnoreNode(node.childNodes[i])) {
res = parsePlistXML(node.childNodes[i]);
if (null != res) new_arr.push(res);
}
}
return new_arr;
} else if (node.nodeName === '#text') {
// TODO: what should we do with text types? (CDATA sections)
} else if (node.nodeName === 'key') {
return node.childNodes[0].nodeValue;
} else if (node.nodeName === 'string') {
res = '';
for (d=0; d < node.childNodes.length; d++) {
res += node.childNodes[d].nodeValue;
}
return res;
} else if (node.nodeName === 'integer') {
// parse as base 10 integer
return parseInt(node.childNodes[0].nodeValue, 10);
} else if (node.nodeName === 'real') {
res = '';
for (d=0; d < node.childNodes.length; d++) {
if (node.childNodes[d].nodeType === 3) {
res += node.childNodes[d].nodeValue;
}
}
return parseFloat(res);
} else if (node.nodeName === 'data') {
res = '';
for (d=0; d < node.childNodes.length; d++) {
if (node.childNodes[d].nodeType === 3) {
res += node.childNodes[d].nodeValue.replace(/\s+/g, '');
}
}
// decode base64 data to a Buffer instance
return new Buffer(res, 'base64');
} else if (node.nodeName === 'date') {
return new Date(node.childNodes[0].nodeValue);
} else if (node.nodeName === 'true') {
return true;
} else if (node.nodeName === 'false') {
return false;
}
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 1 1 3 1 1 1 2 |
var i;
/**
* Parser functions.
*/
var parserFunctions = require('./parse');
for (i in parserFunctions) exports[i] = parserFunctions[i];
/**
* Builder functions.
*/
var builderFunctions = require('./build');
for (i in builderFunctions) exports[i] = builderFunctions[i];
/**
* Add Node.js-specific functions (they're deprecated…).
*/
var nodeFunctions = require('./node');
for (i in nodeFunctions) exports[i] = nodeFunctions[i];
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| b64.js | 23.94% | (17 / 71) | 3.57% | (1 / 28) | 14.29% | (1 / 7) | 23.94% | (17 / 71) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
;(function (exports) {
'use strict';
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var ZERO = '0'.charCodeAt(0)
var PLUS = '+'.charCodeAt(0)
var SLASH = '/'.charCodeAt(0)
var NUMBER = '0'.charCodeAt(0)
var LOWER = 'a'.charCodeAt(0)
var UPPER = 'A'.charCodeAt(0)
function decode (elt) {
var code = elt.charCodeAt(0)
if (code === PLUS)
return 62 // '+'
if (code === SLASH)
return 63 // '/'
if (code < NUMBER)
return -1 //no match
if (code < NUMBER + 10)
return code - NUMBER + 26 + 26
if (code < UPPER + 26)
return code - UPPER
if (code < LOWER + 26)
return code - LOWER + 26
}
function b64ToByteArray (b64) {
var i, j, l, tmp, placeHolders, arr
if (b64.length % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
var len = b64.length
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
// base64 is 4/3 + up to two characters of the original data
arr = new Arr(b64.length * 3 / 4 - placeHolders)
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length
var L = 0
function push (v) {
arr[L++] = v
}
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
push((tmp & 0xFF0000) >> 16)
push((tmp & 0xFF00) >> 8)
push(tmp & 0xFF)
}
if (placeHolders === 2) {
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
push(tmp & 0xFF)
} else if (placeHolders === 1) {
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
push((tmp >> 8) & 0xFF)
push(tmp & 0xFF)
}
return arr
}
function uint8ToBase64 (uint8) {
var i,
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
output = "",
temp, length
function encode (num) {
return lookup.charAt(num)
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
}
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output += tripletToBase64(temp)
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1]
output += encode(temp >> 2)
output += encode((temp << 4) & 0x3F)
output += '=='
break
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
output += encode(temp >> 10)
output += encode((temp >> 4) & 0x3F)
output += encode((temp << 2) & 0x3F)
output += '='
break
}
return output
}
module.exports.toByteArray = b64ToByteArray
module.exports.fromByteArray = uint8ToBase64
}())
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| node.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) |
| 1 2 3 4 5 6 7 8 | 1 |
/**
* For Node.js, simply re-export the core `util.deprecate` function.
*/
module.exports = require('util').deprecate;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| XMLAttribute.js | 47.06% | (8 / 17) | 0% | (0 / 4) | 40% | (2 / 5) | 47.06% | (8 / 17) | |
| XMLBuilder.js | 29.55% | (13 / 44) | 0% | (0 / 30) | 33.33% | (2 / 6) | 29.55% | (13 / 44) | |
| XMLDeclaration.js | 32.69% | (17 / 52) | 0% | (0 / 36) | 57.14% | (4 / 7) | 25% | (11 / 44) | |
| XMLDocType.js | 23.33% | (28 / 120) | 0% | (0 / 36) | 8% | (2 / 25) | 23.33% | (28 / 120) | |
| XMLElement.js | 18.44% | (26 / 141) | 0% | (0 / 63) | 26.67% | (4 / 15) | 15.5% | (20 / 129) | |
| XMLNode.js | 20.1% | (40 / 199) | 0% | (0 / 82) | 5.41% | (2 / 37) | 20.2% | (40 / 198) | |
| XMLProcessingInstruction.js | 25% | (8 / 32) | 0% | (0 / 24) | 40% | (2 / 5) | 25% | (8 / 32) | |
| XMLStringifier.js | 35.11% | (33 / 94) | 0% | (0 / 62) | 7.69% | (2 / 26) | 35.87% | (33 / 92) | |
| index.js | 71.43% | (5 / 7) | 100% | (0 / 0) | 50% | (1 / 2) | 71.43% | (5 / 7) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 1 1 1 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLAttribute, _;
_ = require('lodash-node');
module.exports = XMLAttribute = (function() {
function XMLAttribute(parent, name, value) {
this.stringify = parent.stringify;
if (name == null) {
throw new Error("Missing attribute name");
}
if (value == null) {
throw new Error("Missing attribute value");
}
this.name = this.stringify.attName(name);
this.value = this.stringify.attValue(value);
}
XMLAttribute.prototype.clone = function() {
return _.create(XMLAttribute.prototype, this);
};
XMLAttribute.prototype.toString = function(options, level) {
return ' ' + this.name + '="' + this.value + '"';
};
return XMLAttribute;
})();
}).call(this);
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 1 1 1 1 1 1 1 1 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLBuilder, XMLDeclaration, XMLDocType, XMLElement, XMLStringifier, _;
_ = require('lodash-node');
XMLStringifier = require('./XMLStringifier');
XMLDeclaration = require('./XMLDeclaration');
XMLDocType = require('./XMLDocType');
XMLElement = require('./XMLElement');
module.exports = XMLBuilder = (function() {
function XMLBuilder(name, options) {
var root, temp;
if (name == null) {
throw new Error("Root element needs a name");
}
if (options == null) {
options = {};
}
this.options = options;
this.stringify = new XMLStringifier(options);
temp = new XMLElement(this, 'doc');
root = temp.element(name);
root.isRoot = true;
root.documentObject = this;
this.rootObject = root;
if (!options.headless) {
root.declaration(options);
if ((options.pubID != null) || (options.sysID != null)) {
root.doctype(options);
}
}
}
XMLBuilder.prototype.root = function() {
return this.rootObject;
};
XMLBuilder.prototype.end = function(options) {
return toString(options);
};
XMLBuilder.prototype.toString = function(options) {
var indent, newline, pretty, r;
pretty = (options != null ? options.pretty : void 0) || false;
indent = (options != null ? options.indent : void 0) || ' ';
newline = (options != null ? options.newline : void 0) || '\n';
r = '';
if (this.xmldec != null) {
r += this.xmldec.toString(options);
}
if (this.doctype != null) {
r += this.doctype.toString(options);
}
r += this.rootObject.toString(options);
if (pretty && r.slice(-newline.length) === newline) {
r = r.slice(0, -newline.length);
}
return r;
};
return XMLBuilder;
})();
}).call(this);
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 1 1 1 1 1 1 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLDeclaration, XMLNode, _,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
_ = require('lodash-node');
XMLNode = require('./XMLNode');
module.exports = XMLDeclaration = (function(_super) {
__extends(XMLDeclaration, _super);
function XMLDeclaration(parent, version, encoding, standalone) {
var _ref;
XMLDeclaration.__super__.constructor.call(this, parent);
if (_.isObject(version)) {
_ref = version, version = _ref.version, encoding = _ref.encoding, standalone = _ref.standalone;
}
if (!version) {
version = '1.0';
}
if (version != null) {
this.version = this.stringify.xmlVersion(version);
}
if (encoding != null) {
this.encoding = this.stringify.xmlEncoding(encoding);
}
if (standalone != null) {
this.standalone = this.stringify.xmlStandalone(standalone);
}
}
XMLDeclaration.prototype.clone = function() {
return _.create(XMLDeclaration.prototype, this);
};
XMLDeclaration.prototype.toString = function(options, level) {
var indent, newline, pretty, r, space;
pretty = (options != null ? options.pretty : void 0) || false;
indent = (options != null ? options.indent : void 0) || ' ';
newline = (options != null ? options.newline : void 0) || '\n';
level || (level = 0);
space = new Array(level + 1).join(indent);
r = '';
if (pretty) {
r += space;
}
r += '<?xml';
if (this.version != null) {
r += ' version="' + this.version + '"';
}
if (this.encoding != null) {
r += ' encoding="' + this.encoding + '"';
}
if (this.standalone != null) {
r += ' standalone="' + this.standalone + '"';
}
r += '?>';
if (pretty) {
r += newline;
}
return r;
};
return XMLDeclaration;
})(XMLNode);
}).call(this);
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLDocType, _;
_ = require('lodash-node');
module.exports = XMLDocType = (function() {
function XMLDocType(parent, pubID, sysID) {
var _ref, _ref1;
this.documentObject = parent;
this.stringify = this.documentObject.stringify;
this.children = [];
if (_.isObject(pubID)) {
_ref = pubID, pubID = _ref.pubID, sysID = _ref.sysID;
}
if (sysID == null) {
_ref1 = [pubID, sysID], sysID = _ref1[0], pubID = _ref1[1];
}
if (pubID != null) {
this.pubID = this.stringify.dtdPubID(pubID);
}
if (sysID != null) {
this.sysID = this.stringify.dtdSysID(sysID);
}
}
XMLDocType.prototype.clone = function() {
return _.create(XMLDocType.prototype, this);
};
XMLDocType.prototype.element = function(name, value) {
var XMLDTDElement, child;
XMLDTDElement = require('./XMLDTDElement');
child = new XMLDTDElement(this, name, value);
this.children.push(child);
return this;
};
XMLDocType.prototype.attList = function(elementName, attributeName, attributeType, defaultValueType, defaultValue) {
var XMLDTDAttList, child;
XMLDTDAttList = require('./XMLDTDAttList');
child = new XMLDTDAttList(this, elementName, attributeName, attributeType, defaultValueType, defaultValue);
this.children.push(child);
return this;
};
XMLDocType.prototype.entity = function(name, value) {
var XMLDTDEntity, child;
XMLDTDEntity = require('./XMLDTDEntity');
child = new XMLDTDEntity(this, false, name, value);
this.children.push(child);
return this;
};
XMLDocType.prototype.pEntity = function(name, value) {
var XMLDTDEntity, child;
XMLDTDEntity = require('./XMLDTDEntity');
child = new XMLDTDEntity(this, true, name, value);
this.children.push(child);
return this;
};
XMLDocType.prototype.notation = function(name, value) {
var XMLDTDNotation, child;
XMLDTDNotation = require('./XMLDTDNotation');
child = new XMLDTDNotation(this, name, value);
this.children.push(child);
return this;
};
XMLDocType.prototype.cdata = function(value) {
var XMLCData, child;
XMLCData = require('./XMLCData');
child = new XMLCData(this, value);
this.children.push(child);
return this;
};
XMLDocType.prototype.comment = function(value) {
var XMLComment, child;
XMLComment = require('./XMLComment');
child = new XMLComment(this, value);
this.children.push(child);
return this;
};
XMLDocType.prototype.instruction = function(target, value) {
var XMLProcessingInstruction, child;
XMLProcessingInstruction = require('./XMLProcessingInstruction');
child = new XMLProcessingInstruction(this, target, value);
this.children.push(child);
return this;
};
XMLDocType.prototype.root = function() {
return this.documentObject.root();
};
XMLDocType.prototype.document = function() {
return this.documentObject;
};
XMLDocType.prototype.toString = function(options, level) {
var child, indent, newline, pretty, r, space, _i, _len, _ref;
pretty = (options != null ? options.pretty : void 0) || false;
indent = (options != null ? options.indent : void 0) || ' ';
newline = (options != null ? options.newline : void 0) || '\n';
level || (level = 0);
space = new Array(level + 1).join(indent);
r = '';
if (pretty) {
r += space;
}
r += '<!DOCTYPE ' + this.root().name;
if (this.pubID && this.sysID) {
r += ' PUBLIC "' + this.pubID + '" "' + this.sysID + '"';
} else if (this.sysID) {
r += ' SYSTEM "' + this.sysID + '"';
}
if (this.children.length > 0) {
r += ' [';
if (pretty) {
r += newline;
}
_ref = this.children;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
r += child.toString(options, level + 1);
}
r += ']';
}
r += '>';
if (pretty) {
r += newline;
}
return r;
};
XMLDocType.prototype.ele = function(name, value) {
return this.element(name, value);
};
XMLDocType.prototype.att = function(elementName, attributeName, attributeType, defaultValueType, defaultValue) {
return this.attList(elementName, attributeName, attributeType, defaultValueType, defaultValue);
};
XMLDocType.prototype.ent = function(name, value) {
return this.entity(name, value);
};
XMLDocType.prototype.pent = function(name, value) {
return this.pEntity(name, value);
};
XMLDocType.prototype.not = function(name, value) {
return this.notation(name, value);
};
XMLDocType.prototype.dat = function(value) {
return this.cdata(value);
};
XMLDocType.prototype.com = function(value) {
return this.comment(value);
};
XMLDocType.prototype.ins = function(target, value) {
return this.instruction(target, value);
};
XMLDocType.prototype.up = function() {
return this.root();
};
XMLDocType.prototype.doc = function() {
return this.document();
};
return XMLDocType;
})();
}).call(this);
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLAttribute, XMLElement, XMLNode, XMLProcessingInstruction, _,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
_ = require('lodash-node');
XMLNode = require('./XMLNode');
XMLAttribute = require('./XMLAttribute');
XMLProcessingInstruction = require('./XMLProcessingInstruction');
module.exports = XMLElement = (function(_super) {
__extends(XMLElement, _super);
function XMLElement(parent, name, attributes) {
XMLElement.__super__.constructor.call(this, parent);
if (name == null) {
throw new Error("Missing element name");
}
this.name = this.stringify.eleName(name);
this.children = [];
this.instructions = [];
this.attributes = {};
if (attributes != null) {
this.attribute(attributes);
}
}
XMLElement.prototype.clone = function() {
var att, attName, clonedSelf, pi, _i, _len, _ref, _ref1;
clonedSelf = _.create(XMLElement.prototype, this);
clonedSelf.attributes = {};
_ref = this.attributes;
for (attName in _ref) {
if (!__hasProp.call(_ref, attName)) continue;
att = _ref[attName];
clonedSelf.attributes[attName] = att.clone();
}
clonedSelf.instructions = [];
_ref1 = this.instructions;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
pi = _ref1[_i];
clonedSelf.instructions.push(pi.clone());
}
clonedSelf.children = [];
this.children.forEach(function(child) {
var clonedChild;
clonedChild = child.clone();
clonedChild.parent = clonedSelf;
return clonedSelf.children.push(clonedChild);
});
return clonedSelf;
};
XMLElement.prototype.attribute = function(name, value) {
var attName, attValue;
if (_.isObject(name)) {
for (attName in name) {
if (!__hasProp.call(name, attName)) continue;
attValue = name[attName];
this.attribute(attName, attValue);
}
} else {
if (_.isFunction(value)) {
value = value.apply();
}
if (!this.options.skipNullAttributes || (value != null)) {
this.attributes[name] = new XMLAttribute(this, name, value);
}
}
return this;
};
XMLElement.prototype.removeAttribute = function(name) {
var attName, _i, _len;
if (name == null) {
throw new Error("Missing attribute name");
}
if (_.isArray(name)) {
for (_i = 0, _len = name.length; _i < _len; _i++) {
attName = name[_i];
delete this.attributes[attName];
}
} else {
delete this.attributes[name];
}
return this;
};
XMLElement.prototype.instruction = function(target, value) {
var insTarget, insValue, instruction, _i, _len;
if (_.isArray(target)) {
for (_i = 0, _len = target.length; _i < _len; _i++) {
insTarget = target[_i];
this.instruction(insTarget);
}
} else if (_.isObject(target)) {
for (insTarget in target) {
if (!__hasProp.call(target, insTarget)) continue;
insValue = target[insTarget];
this.instruction(insTarget, insValue);
}
} else {
if (_.isFunction(value)) {
value = value.apply();
}
instruction = new XMLProcessingInstruction(this, target, value);
this.instructions.push(instruction);
}
return this;
};
XMLElement.prototype.toString = function(options, level) {
var att, child, indent, instruction, name, newline, pretty, r, space, _i, _j, _len, _len1, _ref, _ref1, _ref2;
pretty = (options != null ? options.pretty : void 0) || false;
indent = (options != null ? options.indent : void 0) || ' ';
newline = (options != null ? options.newline : void 0) || '\n';
level || (level = 0);
space = new Array(level + 1).join(indent);
r = '';
_ref = this.instructions;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
instruction = _ref[_i];
r += instruction.toString(options, level + 1);
}
if (pretty) {
r += space;
}
r += '<' + this.name;
_ref1 = this.attributes;
for (name in _ref1) {
if (!__hasProp.call(_ref1, name)) continue;
att = _ref1[name];
r += att.toString(options);
}
if (this.children.length === 0) {
r += '/>';
if (pretty) {
r += newline;
}
} else if (pretty && this.children.length === 1 && (this.children[0].value != null)) {
r += '>';
r += this.children[0].value;
r += '</' + this.name + '>';
r += newline;
} else {
r += '>';
if (pretty) {
r += newline;
}
_ref2 = this.children;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
child = _ref2[_j];
r += child.toString(options, level + 1);
}
if (pretty) {
r += space;
}
r += '</' + this.name + '>';
if (pretty) {
r += newline;
}
}
return r;
};
XMLElement.prototype.att = function(name, value) {
return this.attribute(name, value);
};
XMLElement.prototype.ins = function(target, value) {
return this.instruction(target, value);
};
XMLElement.prototype.a = function(name, value) {
return this.attribute(name, value);
};
XMLElement.prototype.i = function(target, value) {
return this.instruction(target, value);
};
return XMLElement;
})(XMLNode);
}).call(this);
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLNode, _,
__hasProp = {}.hasOwnProperty;
_ = require('lodash-node');
module.exports = XMLNode = (function() {
function XMLNode(parent) {
this.parent = parent;
this.options = this.parent.options;
this.stringify = this.parent.stringify;
}
XMLNode.prototype.clone = function() {
throw new Error("Cannot clone generic XMLNode");
};
XMLNode.prototype.element = function(name, attributes, text) {
var item, key, lastChild, val, _i, _len, _ref;
lastChild = null;
if (attributes == null) {
attributes = {};
}
if (!_.isObject(attributes)) {
_ref = [attributes, text], text = _ref[0], attributes = _ref[1];
}
if (_.isArray(name)) {
for (_i = 0, _len = name.length; _i < _len; _i++) {
item = name[_i];
lastChild = this.element(item);
}
} else if (_.isFunction(name)) {
lastChild = this.element(name.apply());
} else if (_.isObject(name)) {
for (key in name) {
if (!__hasProp.call(name, key)) continue;
val = name[key];
if (!(val != null)) {
continue;
}
if (_.isFunction(val)) {
val = val.apply();
}
if (!this.options.ignoreDecorators && this.stringify.convertAttKey && key.indexOf(this.stringify.convertAttKey) === 0) {
lastChild = this.attribute(key.substr(this.stringify.convertAttKey.length), val);
} else if (!this.options.ignoreDecorators && this.stringify.convertPIKey && key.indexOf(this.stringify.convertPIKey) === 0) {
lastChild = this.instruction(key.substr(this.stringify.convertPIKey.length), val);
} else if (_.isObject(val)) {
if (!this.options.ignoreDecorators && this.stringify.convertListKey && key.indexOf(this.stringify.convertListKey) === 0 && _.isArray(val)) {
lastChild = this.element(val);
} else {
lastChild = this.element(key);
lastChild.element(val);
}
} else {
lastChild = this.element(key, val);
}
}
} else {
if (!this.options.ignoreDecorators && this.stringify.convertTextKey && name.indexOf(this.stringify.convertTextKey) === 0) {
lastChild = this.text(text);
} else if (!this.options.ignoreDecorators && this.stringify.convertCDataKey && name.indexOf(this.stringify.convertCDataKey) === 0) {
lastChild = this.cdata(text);
} else if (!this.options.ignoreDecorators && this.stringify.convertCommentKey && name.indexOf(this.stringify.convertCommentKey) === 0) {
lastChild = this.comment(text);
} else if (!this.options.ignoreDecorators && this.stringify.convertRawKey && name.indexOf(this.stringify.convertRawKey) === 0) {
lastChild = this.raw(text);
} else {
lastChild = this.node(name, attributes, text);
}
}
if (lastChild == null) {
throw new Error("Could not create any elements with: " + name);
}
return lastChild;
};
XMLNode.prototype.insertBefore = function(name, attributes, text) {
var child, i, removed;
if (this.isRoot) {
throw new Error("Cannot insert elements at root level");
}
i = this.parent.children.indexOf(this);
removed = this.parent.children.splice(i);
child = this.parent.element(name, attributes, text);
Array.prototype.push.apply(this.parent.children, removed);
return child;
};
XMLNode.prototype.insertAfter = function(name, attributes, text) {
var child, i, removed;
if (this.isRoot) {
throw new Error("Cannot insert elements at root level");
}
i = this.parent.children.indexOf(this);
removed = this.parent.children.splice(i + 1);
child = this.parent.element(name, attributes, text);
Array.prototype.push.apply(this.parent.children, removed);
return child;
};
XMLNode.prototype.remove = function() {
var i, _ref;
if (this.isRoot) {
throw new Error("Cannot remove the root element");
}
i = this.parent.children.indexOf(this);
[].splice.apply(this.parent.children, [i, i - i + 1].concat(_ref = [])), _ref;
return this.parent;
};
XMLNode.prototype.node = function(name, attributes, text) {
var XMLElement, child, _ref;
if (attributes == null) {
attributes = {};
}
if (!_.isObject(attributes)) {
_ref = [attributes, text], text = _ref[0], attributes = _ref[1];
}
XMLElement = require('./XMLElement');
child = new XMLElement(this, name, attributes);
if (text != null) {
child.text(text);
}
this.children.push(child);
return child;
};
XMLNode.prototype.text = function(value) {
var XMLText, child;
XMLText = require('./XMLText');
child = new XMLText(this, value);
this.children.push(child);
return this;
};
XMLNode.prototype.cdata = function(value) {
var XMLCData, child;
XMLCData = require('./XMLCData');
child = new XMLCData(this, value);
this.children.push(child);
return this;
};
XMLNode.prototype.comment = function(value) {
var XMLComment, child;
XMLComment = require('./XMLComment');
child = new XMLComment(this, value);
this.children.push(child);
return this;
};
XMLNode.prototype.raw = function(value) {
var XMLRaw, child;
XMLRaw = require('./XMLRaw');
child = new XMLRaw(this, value);
this.children.push(child);
return this;
};
XMLNode.prototype.declaration = function(version, encoding, standalone) {
var XMLDeclaration, doc, xmldec;
doc = this.document();
XMLDeclaration = require('./XMLDeclaration');
xmldec = new XMLDeclaration(doc, version, encoding, standalone);
doc.xmldec = xmldec;
return doc.root();
};
XMLNode.prototype.doctype = function(pubID, sysID) {
var XMLDocType, doc, doctype;
doc = this.document();
XMLDocType = require('./XMLDocType');
doctype = new XMLDocType(doc, pubID, sysID);
doc.doctype = doctype;
return doctype;
};
XMLNode.prototype.up = function() {
if (this.isRoot) {
throw new Error("The root node has no parent. Use doc() if you need to get the document object.");
}
return this.parent;
};
XMLNode.prototype.root = function() {
var child;
if (this.isRoot) {
return this;
}
child = this.parent;
while (!child.isRoot) {
child = child.parent;
}
return child;
};
XMLNode.prototype.document = function() {
return this.root().documentObject;
};
XMLNode.prototype.end = function(options) {
return this.document().toString(options);
};
XMLNode.prototype.prev = function() {
var i;
if (this.isRoot) {
throw new Error("Root node has no siblings");
}
i = this.parent.children.indexOf(this);
if (i < 1) {
throw new Error("Already at the first node");
}
return this.parent.children[i - 1];
};
XMLNode.prototype.next = function() {
var i;
if (this.isRoot) {
throw new Error("Root node has no siblings");
}
i = this.parent.children.indexOf(this);
if (i === -1 || i === this.parent.children.length - 1) {
throw new Error("Already at the last node");
}
return this.parent.children[i + 1];
};
XMLNode.prototype.importXMLBuilder = function(xmlbuilder) {
var clonedRoot;
clonedRoot = xmlbuilder.root().clone();
clonedRoot.parent = this;
clonedRoot.isRoot = false;
this.children.push(clonedRoot);
return this;
};
XMLNode.prototype.ele = function(name, attributes, text) {
return this.element(name, attributes, text);
};
XMLNode.prototype.nod = function(name, attributes, text) {
return this.node(name, attributes, text);
};
XMLNode.prototype.txt = function(value) {
return this.text(value);
};
XMLNode.prototype.dat = function(value) {
return this.cdata(value);
};
XMLNode.prototype.com = function(value) {
return this.comment(value);
};
XMLNode.prototype.doc = function() {
return this.document();
};
XMLNode.prototype.dec = function(version, encoding, standalone) {
return this.declaration(version, encoding, standalone);
};
XMLNode.prototype.dtd = function(pubID, sysID) {
return this.doctype(pubID, sysID);
};
XMLNode.prototype.e = function(name, attributes, text) {
return this.element(name, attributes, text);
};
XMLNode.prototype.n = function(name, attributes, text) {
return this.node(name, attributes, text);
};
XMLNode.prototype.t = function(value) {
return this.text(value);
};
XMLNode.prototype.d = function(value) {
return this.cdata(value);
};
XMLNode.prototype.c = function(value) {
return this.comment(value);
};
XMLNode.prototype.r = function(value) {
return this.raw(value);
};
XMLNode.prototype.u = function() {
return this.up();
};
return XMLNode;
})();
}).call(this);
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 1 1 1 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLProcessingInstruction, _;
_ = require('lodash-node');
module.exports = XMLProcessingInstruction = (function() {
function XMLProcessingInstruction(parent, target, value) {
this.stringify = parent.stringify;
if (target == null) {
throw new Error("Missing instruction target");
}
this.target = this.stringify.insTarget(target);
if (value) {
this.value = this.stringify.insValue(value);
}
}
XMLProcessingInstruction.prototype.clone = function() {
return _.create(XMLProcessingInstruction.prototype, this);
};
XMLProcessingInstruction.prototype.toString = function(options, level) {
var indent, newline, pretty, r, space;
pretty = (options != null ? options.pretty : void 0) || false;
indent = (options != null ? options.indent : void 0) || ' ';
newline = (options != null ? options.newline : void 0) || '\n';
level || (level = 0);
space = new Array(level + 1).join(indent);
r = '';
if (pretty) {
r += space;
}
r += '<?';
r += this.target;
if (this.value) {
r += ' ' + this.value;
}
r += '?>';
if (pretty) {
r += newline;
}
return r;
};
return XMLProcessingInstruction;
})();
}).call(this);
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLStringifier,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty;
module.exports = XMLStringifier = (function() {
function XMLStringifier(options) {
this.assertLegalChar = __bind(this.assertLegalChar, this);
var key, value, _ref;
this.allowSurrogateChars = options != null ? options.allowSurrogateChars : void 0;
_ref = (options != null ? options.stringify : void 0) || {};
for (key in _ref) {
if (!__hasProp.call(_ref, key)) continue;
value = _ref[key];
this[key] = value;
}
}
XMLStringifier.prototype.eleName = function(val) {
val = '' + val || '';
return this.assertLegalChar(val);
};
XMLStringifier.prototype.eleText = function(val) {
val = '' + val || '';
return this.assertLegalChar(this.escape(val));
};
XMLStringifier.prototype.cdata = function(val) {
val = '' + val || '';
if (val.match(/]]>/)) {
throw new Error("Invalid CDATA text: " + val);
}
return this.assertLegalChar(val);
};
XMLStringifier.prototype.comment = function(val) {
val = '' + val || '';
if (val.match(/--/)) {
throw new Error("Comment text cannot contain double-hypen: " + val);
}
return this.assertLegalChar(this.escape(val));
};
XMLStringifier.prototype.raw = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.attName = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.attValue = function(val) {
val = '' + val || '';
return this.escape(val);
};
XMLStringifier.prototype.insTarget = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.insValue = function(val) {
val = '' + val || '';
if (val.match(/\?>/)) {
throw new Error("Invalid processing instruction value: " + val);
}
return val;
};
XMLStringifier.prototype.xmlVersion = function(val) {
val = '' + val || '';
if (!val.match(/1\.[0-9]+/)) {
throw new Error("Invalid version number: " + val);
}
return val;
};
XMLStringifier.prototype.xmlEncoding = function(val) {
val = '' + val || '';
if (!val.match(/[A-Za-z](?:[A-Za-z0-9._-]|-)*/)) {
throw new Error("Invalid encoding: " + options.val);
}
return val;
};
XMLStringifier.prototype.xmlStandalone = function(val) {
if (val) {
return "yes";
} else {
return "no";
}
};
XMLStringifier.prototype.dtdPubID = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.dtdSysID = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.dtdElementValue = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.dtdAttType = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.dtdAttDefault = function(val) {
if (val != null) {
return '' + val || '';
} else {
return val;
}
};
XMLStringifier.prototype.dtdEntityValue = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.dtdNData = function(val) {
return '' + val || '';
};
XMLStringifier.prototype.convertAttKey = '@';
XMLStringifier.prototype.convertPIKey = '?';
XMLStringifier.prototype.convertTextKey = '#text';
XMLStringifier.prototype.convertCDataKey = '#cdata';
XMLStringifier.prototype.convertCommentKey = '#comment';
XMLStringifier.prototype.convertRawKey = '#raw';
XMLStringifier.prototype.convertListKey = '#list';
XMLStringifier.prototype.assertLegalChar = function(str) {
var chars, chr;
if (this.allowSurrogateChars) {
chars = /[\u0000-\u0008\u000B-\u000C\u000E-\u001F\uFFFE-\uFFFF]/;
} else {
chars = /[\u0000-\u0008\u000B-\u000C\u000E-\u001F\uD800-\uDFFF\uFFFE-\uFFFF]/;
}
chr = str.match(chars);
if (chr) {
throw new Error("Invalid character (" + chr + ") in string: " + str + " at index " + chr.index);
}
return str;
};
XMLStringifier.prototype.escape = function(str) {
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/'/g, ''').replace(/"/g, '"');
};
return XMLStringifier;
})();
}).call(this);
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 1 1 1 1 1 | // Generated by CoffeeScript 1.6.3
(function() {
var XMLBuilder, _;
_ = require('lodash-node');
XMLBuilder = require('./XMLBuilder');
module.exports.create = function(name, xmldec, doctype, options) {
options = _.extend({}, xmldec, doctype, options);
return new XMLBuilder(name, options).root();
};
}).call(this);
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| arrays.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) | |
| chaining.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) | |
| collections.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) | |
| functions.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) | |
| index.js | 95.83% | (184 / 192) | 25.93% | (7 / 27) | 61.54% | (8 / 13) | 95.83% | (184 / 192) | |
| objects.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) | |
| support.js | 85.71% | (6 / 7) | 100% | (2 / 2) | 0% | (0 / 1) | 100% | (6 / 6) | |
| utilities.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
module.exports = {
'compact': require('./arrays/compact'),
'difference': require('./arrays/difference'),
'drop': require('./arrays/rest'),
'findIndex': require('./arrays/findIndex'),
'findLastIndex': require('./arrays/findLastIndex'),
'first': require('./arrays/first'),
'flatten': require('./arrays/flatten'),
'head': require('./arrays/first'),
'indexOf': require('./arrays/indexOf'),
'initial': require('./arrays/initial'),
'intersection': require('./arrays/intersection'),
'last': require('./arrays/last'),
'lastIndexOf': require('./arrays/lastIndexOf'),
'object': require('./arrays/zipObject'),
'pull': require('./arrays/pull'),
'range': require('./arrays/range'),
'remove': require('./arrays/remove'),
'rest': require('./arrays/rest'),
'sortedIndex': require('./arrays/sortedIndex'),
'tail': require('./arrays/rest'),
'take': require('./arrays/first'),
'union': require('./arrays/union'),
'uniq': require('./arrays/uniq'),
'unique': require('./arrays/uniq'),
'unzip': require('./arrays/zip'),
'without': require('./arrays/without'),
'xor': require('./arrays/xor'),
'zip': require('./arrays/zip'),
'zipObject': require('./arrays/zipObject')
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
module.exports = {
'chain': require('./chaining/chain'),
'tap': require('./chaining/tap'),
'value': require('./chaining/wrapperValueOf'),
'wrapperChain': require('./chaining/wrapperChain'),
'wrapperToString': require('./chaining/wrapperToString'),
'wrapperValueOf': require('./chaining/wrapperValueOf')
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
module.exports = {
'all': require('./collections/every'),
'any': require('./collections/some'),
'at': require('./collections/at'),
'collect': require('./collections/map'),
'contains': require('./collections/contains'),
'countBy': require('./collections/countBy'),
'detect': require('./collections/find'),
'each': require('./collections/forEach'),
'eachRight': require('./collections/forEachRight'),
'every': require('./collections/every'),
'filter': require('./collections/filter'),
'find': require('./collections/find'),
'findLast': require('./collections/findLast'),
'findWhere': require('./collections/find'),
'foldl': require('./collections/reduce'),
'foldr': require('./collections/reduceRight'),
'forEach': require('./collections/forEach'),
'forEachRight': require('./collections/forEachRight'),
'groupBy': require('./collections/groupBy'),
'include': require('./collections/contains'),
'indexBy': require('./collections/indexBy'),
'inject': require('./collections/reduce'),
'invoke': require('./collections/invoke'),
'map': require('./collections/map'),
'max': require('./collections/max'),
'min': require('./collections/min'),
'pluck': require('./collections/pluck'),
'reduce': require('./collections/reduce'),
'reduceRight': require('./collections/reduceRight'),
'reject': require('./collections/reject'),
'sample': require('./collections/sample'),
'select': require('./collections/filter'),
'shuffle': require('./collections/shuffle'),
'size': require('./collections/size'),
'some': require('./collections/some'),
'sortBy': require('./collections/sortBy'),
'toArray': require('./collections/toArray'),
'where': require('./collections/where')
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
module.exports = {
'after': require('./functions/after'),
'bind': require('./functions/bind'),
'bindAll': require('./functions/bindAll'),
'bindKey': require('./functions/bindKey'),
'compose': require('./functions/compose'),
'createCallback': require('./functions/createCallback'),
'curry': require('./functions/curry'),
'debounce': require('./functions/debounce'),
'defer': require('./functions/defer'),
'delay': require('./functions/delay'),
'memoize': require('./functions/memoize'),
'once': require('./functions/once'),
'partial': require('./functions/partial'),
'partialRight': require('./functions/partialRight'),
'throttle': require('./functions/throttle'),
'wrap': require('./functions/wrap')
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 136 55 1 1 1 1 1 1 1 141 141 5 1 1 1 1 1 1 3 3 1 4 4 1 3 3 1 1 1 | /**
* @license
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var arrays = require('./arrays'),
chaining = require('./chaining'),
collections = require('./collections'),
functions = require('./functions'),
objects = require('./objects'),
utilities = require('./utilities'),
forEach = require('./collections/forEach'),
forOwn = require('./objects/forOwn'),
isArray = require('./objects/isArray'),
lodashWrapper = require('./internals/lodashWrapper'),
mixin = require('./utilities/mixin'),
support = require('./support'),
templateSettings = require('./utilities/templateSettings');
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Used for native method references */
var objectProto = Object.prototype;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Creates a `lodash` object which wraps the given value to enable intuitive
* method chaining.
*
* In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
* and `unshift`
*
* Chaining is supported in custom builds as long as the `value` method is
* implicitly or explicitly included in the build.
*
* The chainable wrapper functions are:
* `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
* `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
* `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
* `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
* `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
* `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
* `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
* `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
* `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
* `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
* and `zip`
*
* The non-chainable wrapper functions are:
* `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
* `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
* `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
* `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
* `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
* `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
* `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
* `template`, `unescape`, `uniqueId`, and `value`
*
* The wrapper functions `first` and `last` return wrapped values when `n` is
* provided, otherwise they return unwrapped values.
*
* Explicit chaining can be enabled by using the `_.chain` method.
*
* @name _
* @constructor
* @category Chaining
* @param {*} value The value to wrap in a `lodash` instance.
* @returns {Object} Returns a `lodash` instance.
* @example
*
* var wrapped = _([1, 2, 3]);
*
* // returns an unwrapped value
* wrapped.reduce(function(sum, num) {
* return sum + num;
* });
* // => 6
*
* // returns a wrapped value
* var squares = wrapped.map(function(num) {
* return num * num;
* });
*
* _.isArray(squares);
* // => false
*
* _.isArray(squares.value());
* // => true
*/
function lodash(value) {
// don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
? value
: new lodashWrapper(value);
}
// ensure `new lodashWrapper` is an instance of `lodash`
lodashWrapper.prototype = lodash.prototype;
// wrap `_.mixin` so it works when provided only one argument
mixin = (function(fn) {
var functions = objects.functions;
return function(object, source, options) {
Eif (!source || (!options && !functions(source).length)) {
Eif (options == null) {
options = source;
}
source = object;
object = lodash;
}
return fn(object, source, options);
};
}(mixin));
// add functions that return wrapped values when chaining
lodash.after = functions.after;
lodash.assign = objects.assign;
lodash.at = collections.at;
lodash.bind = functions.bind;
lodash.bindAll = functions.bindAll;
lodash.bindKey = functions.bindKey;
lodash.chain = chaining.chain;
lodash.compact = arrays.compact;
lodash.compose = functions.compose;
lodash.constant = utilities.constant;
lodash.countBy = collections.countBy;
lodash.create = objects.create;
lodash.createCallback = functions.createCallback;
lodash.curry = functions.curry;
lodash.debounce = functions.debounce;
lodash.defaults = objects.defaults;
lodash.defer = functions.defer;
lodash.delay = functions.delay;
lodash.difference = arrays.difference;
lodash.filter = collections.filter;
lodash.flatten = arrays.flatten;
lodash.forEach = forEach;
lodash.forEachRight = collections.forEachRight;
lodash.forIn = objects.forIn;
lodash.forInRight = objects.forInRight;
lodash.forOwn = forOwn;
lodash.forOwnRight = objects.forOwnRight;
lodash.functions = objects.functions;
lodash.groupBy = collections.groupBy;
lodash.indexBy = collections.indexBy;
lodash.initial = arrays.initial;
lodash.intersection = arrays.intersection;
lodash.invert = objects.invert;
lodash.invoke = collections.invoke;
lodash.keys = objects.keys;
lodash.map = collections.map;
lodash.mapValues = objects.mapValues;
lodash.max = collections.max;
lodash.memoize = functions.memoize;
lodash.merge = objects.merge;
lodash.min = collections.min;
lodash.omit = objects.omit;
lodash.once = functions.once;
lodash.pairs = objects.pairs;
lodash.partial = functions.partial;
lodash.partialRight = functions.partialRight;
lodash.pick = objects.pick;
lodash.pluck = collections.pluck;
lodash.property = utilities.property;
lodash.pull = arrays.pull;
lodash.range = arrays.range;
lodash.reject = collections.reject;
lodash.remove = arrays.remove;
lodash.rest = arrays.rest;
lodash.shuffle = collections.shuffle;
lodash.sortBy = collections.sortBy;
lodash.tap = chaining.tap;
lodash.throttle = functions.throttle;
lodash.times = utilities.times;
lodash.toArray = collections.toArray;
lodash.transform = objects.transform;
lodash.union = arrays.union;
lodash.uniq = arrays.uniq;
lodash.values = objects.values;
lodash.where = collections.where;
lodash.without = arrays.without;
lodash.wrap = functions.wrap;
lodash.xor = arrays.xor;
lodash.zip = arrays.zip;
lodash.zipObject = arrays.zipObject;
// add aliases
lodash.collect = collections.map;
lodash.drop = arrays.rest;
lodash.each = forEach;
lodash.eachRight = collections.forEachRight;
lodash.extend = objects.assign;
lodash.methods = objects.functions;
lodash.object = arrays.zipObject;
lodash.select = collections.filter;
lodash.tail = arrays.rest;
lodash.unique = arrays.uniq;
lodash.unzip = arrays.zip;
// add functions to `lodash.prototype`
mixin(lodash);
// add functions that return unwrapped values when chaining
lodash.clone = objects.clone;
lodash.cloneDeep = objects.cloneDeep;
lodash.contains = collections.contains;
lodash.escape = utilities.escape;
lodash.every = collections.every;
lodash.find = collections.find;
lodash.findIndex = arrays.findIndex;
lodash.findKey = objects.findKey;
lodash.findLast = collections.findLast;
lodash.findLastIndex = arrays.findLastIndex;
lodash.findLastKey = objects.findLastKey;
lodash.has = objects.has;
lodash.identity = utilities.identity;
lodash.indexOf = arrays.indexOf;
lodash.isArguments = objects.isArguments;
lodash.isArray = isArray;
lodash.isBoolean = objects.isBoolean;
lodash.isDate = objects.isDate;
lodash.isElement = objects.isElement;
lodash.isEmpty = objects.isEmpty;
lodash.isEqual = objects.isEqual;
lodash.isFinite = objects.isFinite;
lodash.isFunction = objects.isFunction;
lodash.isNaN = objects.isNaN;
lodash.isNull = objects.isNull;
lodash.isNumber = objects.isNumber;
lodash.isObject = objects.isObject;
lodash.isPlainObject = objects.isPlainObject;
lodash.isRegExp = objects.isRegExp;
lodash.isString = objects.isString;
lodash.isUndefined = objects.isUndefined;
lodash.lastIndexOf = arrays.lastIndexOf;
lodash.mixin = mixin;
lodash.noConflict = utilities.noConflict;
lodash.noop = utilities.noop;
lodash.now = utilities.now;
lodash.parseInt = utilities.parseInt;
lodash.random = utilities.random;
lodash.reduce = collections.reduce;
lodash.reduceRight = collections.reduceRight;
lodash.result = utilities.result;
lodash.size = collections.size;
lodash.some = collections.some;
lodash.sortedIndex = arrays.sortedIndex;
lodash.template = utilities.template;
lodash.unescape = utilities.unescape;
lodash.uniqueId = utilities.uniqueId;
// add aliases
lodash.all = collections.every;
lodash.any = collections.some;
lodash.detect = collections.find;
lodash.findWhere = collections.find;
lodash.foldl = collections.reduce;
lodash.foldr = collections.reduceRight;
lodash.include = collections.contains;
lodash.inject = collections.reduce;
mixin(function() {
var source = {}
forOwn(lodash, function(func, methodName) {
if (!lodash.prototype[methodName]) {
source[methodName] = func;
}
});
return source;
}(), false);
// add functions capable of returning wrapped and unwrapped values when chaining
lodash.first = arrays.first;
lodash.last = arrays.last;
lodash.sample = collections.sample;
// add aliases
lodash.take = arrays.first;
lodash.head = arrays.first;
forOwn(lodash, function(func, methodName) {
var callbackable = methodName !== 'sample';
if (!lodash.prototype[methodName]) {
lodash.prototype[methodName]= function(n, guard) {
var chainAll = this.__chain__,
result = func(this.__wrapped__, n, guard);
return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
? result
: new lodashWrapper(result, chainAll);
};
}
});
/**
* The semantic version number.
*
* @static
* @memberOf _
* @type string
*/
lodash.VERSION = '2.4.1';
// add "Chaining" functions to the wrapper
lodash.prototype.chain = chaining.wrapperChain;
lodash.prototype.toString = chaining.wrapperToString;
lodash.prototype.value = chaining.wrapperValueOf;
lodash.prototype.valueOf = chaining.wrapperValueOf;
// add `Array` functions that return unwrapped values
forEach(['join', 'pop', 'shift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
var chainAll = this.__chain__,
result = func.apply(this.__wrapped__, arguments);
return chainAll
? new lodashWrapper(result, chainAll)
: result;
};
});
// add `Array` functions that return the existing wrapped value
forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
func.apply(this.__wrapped__, arguments);
return this;
};
});
// add `Array` functions that return new wrapped values
forEach(['concat', 'slice', 'splice'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
};
});
lodash.support = support;
(lodash.templateSettings = utilities.templateSettings).imports._ = lodash;
module.exports = lodash;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
module.exports = {
'assign': require('./objects/assign'),
'clone': require('./objects/clone'),
'cloneDeep': require('./objects/cloneDeep'),
'create': require('./objects/create'),
'defaults': require('./objects/defaults'),
'extend': require('./objects/assign'),
'findKey': require('./objects/findKey'),
'findLastKey': require('./objects/findLastKey'),
'forIn': require('./objects/forIn'),
'forInRight': require('./objects/forInRight'),
'forOwn': require('./objects/forOwn'),
'forOwnRight': require('./objects/forOwnRight'),
'functions': require('./objects/functions'),
'has': require('./objects/has'),
'invert': require('./objects/invert'),
'isArguments': require('./objects/isArguments'),
'isArray': require('./objects/isArray'),
'isBoolean': require('./objects/isBoolean'),
'isDate': require('./objects/isDate'),
'isElement': require('./objects/isElement'),
'isEmpty': require('./objects/isEmpty'),
'isEqual': require('./objects/isEqual'),
'isFinite': require('./objects/isFinite'),
'isFunction': require('./objects/isFunction'),
'isNaN': require('./objects/isNaN'),
'isNull': require('./objects/isNull'),
'isNumber': require('./objects/isNumber'),
'isObject': require('./objects/isObject'),
'isPlainObject': require('./objects/isPlainObject'),
'isRegExp': require('./objects/isRegExp'),
'isString': require('./objects/isString'),
'isUndefined': require('./objects/isUndefined'),
'keys': require('./objects/keys'),
'mapValues': require('./objects/mapValues'),
'merge': require('./objects/merge'),
'methods': require('./objects/functions'),
'omit': require('./objects/omit'),
'pairs': require('./objects/pairs'),
'pick': require('./objects/pick'),
'transform': require('./objects/transform'),
'values': require('./objects/values')
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNative = require('./internals/isNative');
/** Used to detect functions containing a `this` reference */
var reThis = /\bthis\b/;
/**
* An object used to flag environments features.
*
* @static
* @memberOf _
* @type Object
*/
var support = {};
/**
* Detect if functions can be decompiled by `Function#toString`
* (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
*
* @memberOf _.support
* @type boolean
*/
support.funcDecomp = !isNative(global.WinRTError) && reThis.test(function() { return this; });
/**
* Detect if `Function#name` is supported (all but IE).
*
* @memberOf _.support
* @type boolean
*/
support.funcNames = typeof Function.name == 'string';
module.exports = support;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
module.exports = {
'constant': require('./utilities/constant'),
'createCallback': require('./functions/createCallback'),
'escape': require('./utilities/escape'),
'identity': require('./utilities/identity'),
'mixin': require('./utilities/mixin'),
'noConflict': require('./utilities/noConflict'),
'noop': require('./utilities/noop'),
'now': require('./utilities/now'),
'parseInt': require('./utilities/parseInt'),
'property': require('./utilities/property'),
'random': require('./utilities/random'),
'result': require('./utilities/result'),
'template': require('./utilities/template'),
'templateSettings': require('./utilities/templateSettings'),
'times': require('./utilities/times'),
'unescape': require('./utilities/unescape'),
'uniqueId': require('./utilities/uniqueId')
};
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| compact.js | 25% | (2 / 8) | 0% | (0 / 4) | 0% | (0 / 1) | 25% | (2 / 8) | |
| difference.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| findIndex.js | 33.33% | (3 / 9) | 0% | (0 / 4) | 0% | (0 / 1) | 33.33% | (3 / 9) | |
| findLastIndex.js | 33.33% | (3 / 9) | 0% | (0 / 4) | 0% | (0 / 1) | 33.33% | (3 / 9) | |
| first.js | 28.57% | (4 / 14) | 0% | (0 / 14) | 0% | (0 / 1) | 28.57% | (4 / 14) | |
| flatten.js | 30% | (3 / 10) | 0% | (0 / 11) | 0% | (0 / 1) | 30% | (3 / 10) | |
| indexOf.js | 36.36% | (4 / 11) | 0% | (0 / 12) | 0% | (0 / 1) | 36.36% | (4 / 11) | |
| initial.js | 33.33% | (4 / 12) | 0% | (0 / 14) | 0% | (0 / 1) | 33.33% | (4 / 12) | |
| intersection.js | 10.34% | (3 / 29) | 0% | (0 / 23) | 0% | (0 / 1) | 10.34% | (3 / 29) | |
| last.js | 28.57% | (4 / 14) | 0% | (0 / 14) | 0% | (0 / 1) | 28.57% | (4 / 14) | |
| lastIndexOf.js | 30% | (3 / 10) | 0% | (0 / 8) | 0% | (0 / 1) | 30% | (3 / 10) | |
| pull.js | 33.33% | (4 / 12) | 0% | (0 / 4) | 0% | (0 / 1) | 33.33% | (4 / 12) | |
| range.js | 28.57% | (4 / 14) | 0% | (0 / 10) | 0% | (0 / 1) | 28.57% | (4 / 14) | |
| remove.js | 35.71% | (5 / 14) | 0% | (0 / 4) | 0% | (0 / 1) | 35.71% | (5 / 14) | |
| rest.js | 36.36% | (4 / 11) | 0% | (0 / 12) | 0% | (0 / 1) | 36.36% | (4 / 11) | |
| sortedIndex.js | 30% | (3 / 10) | 0% | (0 / 6) | 0% | (0 / 1) | 30% | (3 / 10) | |
| union.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| uniq.js | 30% | (3 / 10) | 0% | (0 / 11) | 0% | (0 / 1) | 30% | (3 / 10) | |
| without.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| xor.js | 33.33% | (3 / 9) | 0% | (0 / 8) | 0% | (0 / 1) | 33.33% | (3 / 9) | |
| zip.js | 42.86% | (3 / 7) | 0% | (0 / 6) | 0% | (0 / 1) | 42.86% | (3 / 7) | |
| zipObject.js | 23.08% | (3 / 13) | 0% | (0 / 11) | 0% | (0 / 1) | 23.08% | (3 / 13) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Creates an array with all falsey values removed. The values `false`, `null`,
* `0`, `""`, `undefined`, and `NaN` are all falsey.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to compact.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.compact([0, 1, false, 2, '', 3]);
* // => [1, 2, 3]
*/
function compact(array) {
var index = -1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (value) {
result.push(value);
}
}
return result;
}
module.exports = compact;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseDifference = require('../internals/baseDifference'),
baseFlatten = require('../internals/baseFlatten');
/**
* Creates an array excluding all values of the provided arrays using strict
* equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to process.
* @param {...Array} [values] The arrays of values to exclude.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
* // => [1, 3, 4]
*/
function difference(array) {
return baseDifference(array, baseFlatten(arguments, true, true, 1));
}
module.exports = difference;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback');
/**
* This method is like `_.find` except that it returns the index of the first
* element that passes the callback check, instead of the element itself.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true },
* { 'name': 'pebbles', 'age': 1, 'blocked': false }
* ];
*
* _.findIndex(characters, function(chr) {
* return chr.age < 20;
* });
* // => 2
*
* // using "_.where" callback shorthand
* _.findIndex(characters, { 'age': 36 });
* // => 0
*
* // using "_.pluck" callback shorthand
* _.findIndex(characters, 'blocked');
* // => 1
*/
function findIndex(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0;
callback = createCallback(callback, thisArg, 3);
while (++index < length) {
if (callback(array[index], index, array)) {
return index;
}
}
return -1;
}
module.exports = findIndex;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback');
/**
* This method is like `_.findIndex` except that it iterates over elements
* of a `collection` from right to left.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': true },
* { 'name': 'fred', 'age': 40, 'blocked': false },
* { 'name': 'pebbles', 'age': 1, 'blocked': true }
* ];
*
* _.findLastIndex(characters, function(chr) {
* return chr.age > 30;
* });
* // => 1
*
* // using "_.where" callback shorthand
* _.findLastIndex(characters, { 'age': 36 });
* // => 0
*
* // using "_.pluck" callback shorthand
* _.findLastIndex(characters, 'blocked');
* // => 2
*/
function findLastIndex(array, callback, thisArg) {
var length = array ? array.length : 0;
callback = createCallback(callback, thisArg, 3);
while (length--) {
if (callback(array[length], length, array)) {
return length;
}
}
return -1;
}
module.exports = findLastIndex;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
slice = require('../internals/slice');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max,
nativeMin = Math.min;
/**
* Gets the first element or first `n` elements of an array. If a callback
* is provided elements at the beginning of the array are returned as long
* as the callback returns truey. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias head, take
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback] The function called
* per element or the number of elements to return. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the first element(s) of `array`.
* @example
*
* _.first([1, 2, 3]);
* // => 1
*
* _.first([1, 2, 3], 2);
* // => [1, 2]
*
* _.first([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [1, 2]
*
* var characters = [
* { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.first(characters, 'blocked');
* // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
*
* // using "_.where" callback shorthand
* _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
* // => ['barney', 'fred']
*/
function first(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = -1;
callback = createCallback(callback, thisArg, 3);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array ? array[0] : undefined;
}
}
return slice(array, 0, nativeMin(nativeMax(0, n), length));
}
module.exports = first;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseFlatten = require('../internals/baseFlatten'),
map = require('../collections/map');
/**
* Flattens a nested array (the nesting can be to any depth). If `isShallow`
* is truey, the array will only be flattened a single level. If a callback
* is provided each element of the array is passed through the callback before
* flattening. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new flattened array.
* @example
*
* _.flatten([1, [2], [3, [[4]]]]);
* // => [1, 2, 3, 4];
*
* _.flatten([1, [2], [3, [[4]]]], true);
* // => [1, 2, 3, [[4]]];
*
* var characters = [
* { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
* { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
* ];
*
* // using "_.pluck" callback shorthand
* _.flatten(characters, 'pets');
* // => ['hoppy', 'baby puss', 'dino']
*/
function flatten(array, isShallow, callback, thisArg) {
// juggle arguments
if (typeof isShallow != 'boolean' && isShallow != null) {
thisArg = callback;
callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
isShallow = false;
}
if (callback != null) {
array = map(array, callback, thisArg);
}
return baseFlatten(array, isShallow);
}
module.exports = flatten;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseIndexOf = require('../internals/baseIndexOf'),
sortedIndex = require('./sortedIndex');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max;
/**
* Gets the index at which the first occurrence of `value` is found using
* strict equality for comparisons, i.e. `===`. If the array is already sorted
* providing `true` for `fromIndex` will run a faster binary search.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {boolean|number} [fromIndex=0] The index to search from or `true`
* to perform a binary search on a sorted array.
* @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2);
* // => 1
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
* // => 4
*
* _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
* // => 2
*/
function indexOf(array, value, fromIndex) {
if (typeof fromIndex == 'number') {
var length = array ? array.length : 0;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
} else if (fromIndex) {
var index = sortedIndex(array, value);
return array[index] === value ? index : -1;
}
return baseIndexOf(array, value, fromIndex);
}
module.exports = indexOf;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
slice = require('../internals/slice');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max,
nativeMin = Math.min;
/**
* Gets all but the last element or last `n` elements of an array. If a
* callback is provided elements at the end of the array are excluded from
* the result as long as the callback returns truey. The callback is bound
* to `thisArg` and invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback=1] The function called
* per element or the number of elements to exclude. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.initial([1, 2, 3]);
* // => [1, 2]
*
* _.initial([1, 2, 3], 2);
* // => [1]
*
* _.initial([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [1]
*
* var characters = [
* { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.initial(characters, 'blocked');
* // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }]
*
* // using "_.where" callback shorthand
* _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
* // => ['barney', 'fred']
*/
function initial(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = length;
callback = createCallback(callback, thisArg, 3);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : callback || n;
}
return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
}
module.exports = initial;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseIndexOf = require('../internals/baseIndexOf'),
cacheIndexOf = require('../internals/cacheIndexOf'),
createCache = require('../internals/createCache'),
getArray = require('../internals/getArray'),
isArguments = require('../objects/isArguments'),
isArray = require('../objects/isArray'),
largeArraySize = require('../internals/largeArraySize'),
releaseArray = require('../internals/releaseArray'),
releaseObject = require('../internals/releaseObject');
/**
* Creates an array of unique values present in all provided arrays using
* strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of shared values.
* @example
*
* _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
* // => [1, 2]
*/
function intersection() {
var args = [],
argsIndex = -1,
argsLength = arguments.length,
caches = getArray(),
indexOf = baseIndexOf,
trustIndexOf = indexOf === baseIndexOf,
seen = getArray();
while (++argsIndex < argsLength) {
var value = arguments[argsIndex];
if (isArray(value) || isArguments(value)) {
args.push(value);
caches.push(trustIndexOf && value.length >= largeArraySize &&
createCache(argsIndex ? args[argsIndex] : seen));
}
}
var array = args[0],
index = -1,
length = array ? array.length : 0,
result = [];
outer:
while (++index < length) {
var cache = caches[0];
value = array[index];
if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
argsIndex = argsLength;
(cache || seen).push(value);
while (--argsIndex) {
cache = caches[argsIndex];
if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
continue outer;
}
}
result.push(value);
}
}
while (argsLength--) {
cache = caches[argsLength];
if (cache) {
releaseObject(cache);
}
}
releaseArray(caches);
releaseArray(seen);
return result;
}
module.exports = intersection;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
slice = require('../internals/slice');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max;
/**
* Gets the last element or last `n` elements of an array. If a callback is
* provided elements at the end of the array are returned as long as the
* callback returns truey. The callback is bound to `thisArg` and invoked
* with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback] The function called
* per element or the number of elements to return. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the last element(s) of `array`.
* @example
*
* _.last([1, 2, 3]);
* // => 3
*
* _.last([1, 2, 3], 2);
* // => [2, 3]
*
* _.last([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [2, 3]
*
* var characters = [
* { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.pluck(_.last(characters, 'blocked'), 'name');
* // => ['fred', 'pebbles']
*
* // using "_.where" callback shorthand
* _.last(characters, { 'employer': 'na' });
* // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
*/
function last(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = length;
callback = createCallback(callback, thisArg, 3);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array ? array[length - 1] : undefined;
}
}
return slice(array, nativeMax(0, length - n));
}
module.exports = last;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max,
nativeMin = Math.min;
/**
* Gets the index at which the last occurrence of `value` is found using strict
* equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
* as the offset from the end of the collection.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
* // => 4
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
* // => 1
*/
function lastIndexOf(array, value, fromIndex) {
var index = array ? array.length : 0;
if (typeof fromIndex == 'number') {
index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
}
while (index--) {
if (array[index] === value) {
return index;
}
}
return -1;
}
module.exports = lastIndexOf;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Native method shortcuts */
var splice = arrayRef.splice;
/**
* Removes all provided values from the given array using strict equality for
* comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to modify.
* @param {...*} [value] The values to remove.
* @returns {Array} Returns `array`.
* @example
*
* var array = [1, 2, 3, 1, 2, 3];
* _.pull(array, 2, 3);
* console.log(array);
* // => [1, 1]
*/
function pull(array) {
var args = arguments,
argsIndex = 0,
argsLength = args.length,
length = array ? array.length : 0;
while (++argsIndex < argsLength) {
var index = -1,
value = args[argsIndex];
while (++index < length) {
if (array[index] === value) {
splice.call(array, index--, 1);
length--;
}
}
}
return array;
}
module.exports = pull;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Native method shortcuts */
var ceil = Math.ceil;
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max;
/**
* Creates an array of numbers (positive and/or negative) progressing from
* `start` up to but not including `end`. If `start` is less than `stop` a
* zero-length range is created unless a negative `step` is specified.
*
* @static
* @memberOf _
* @category Arrays
* @param {number} [start=0] The start of the range.
* @param {number} end The end of the range.
* @param {number} [step=1] The value to increment or decrement by.
* @returns {Array} Returns a new range array.
* @example
*
* _.range(4);
* // => [0, 1, 2, 3]
*
* _.range(1, 5);
* // => [1, 2, 3, 4]
*
* _.range(0, 20, 5);
* // => [0, 5, 10, 15]
*
* _.range(0, -4, -1);
* // => [0, -1, -2, -3]
*
* _.range(1, 4, 0);
* // => [1, 1, 1]
*
* _.range(0);
* // => []
*/
function range(start, end, step) {
start = +start || 0;
step = typeof step == 'number' ? step : (+step || 1);
if (end == null) {
end = start;
start = 0;
}
// use `Array(length)` so engines like Chakra and V8 avoid slower modes
// http://youtu.be/XAqIpGU8ZZk#t=17m25s
var index = -1,
length = nativeMax(0, ceil((end - start) / (step || 1))),
result = Array(length);
while (++index < length) {
result[index] = start;
start += step;
}
return result;
}
module.exports = range;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback');
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Native method shortcuts */
var splice = arrayRef.splice;
/**
* Removes all elements from an array that the callback returns truey for
* and returns an array of removed elements. The callback is bound to `thisArg`
* and invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to modify.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of removed elements.
* @example
*
* var array = [1, 2, 3, 4, 5, 6];
* var evens = _.remove(array, function(num) { return num % 2 == 0; });
*
* console.log(array);
* // => [1, 3, 5]
*
* console.log(evens);
* // => [2, 4, 6]
*/
function remove(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0,
result = [];
callback = createCallback(callback, thisArg, 3);
while (++index < length) {
var value = array[index];
if (callback(value, index, array)) {
result.push(value);
splice.call(array, index--, 1);
length--;
}
}
return result;
}
module.exports = remove;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
slice = require('../internals/slice');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max;
/**
* The opposite of `_.initial` this method gets all but the first element or
* first `n` elements of an array. If a callback function is provided elements
* at the beginning of the array are excluded from the result as long as the
* callback returns truey. The callback is bound to `thisArg` and invoked
* with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias drop, tail
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback=1] The function called
* per element or the number of elements to exclude. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.rest([1, 2, 3]);
* // => [2, 3]
*
* _.rest([1, 2, 3], 2);
* // => [3]
*
* _.rest([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [3]
*
* var characters = [
* { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.pluck(_.rest(characters, 'blocked'), 'name');
* // => ['fred', 'pebbles']
*
* // using "_.where" callback shorthand
* _.rest(characters, { 'employer': 'slate' });
* // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
*/
function rest(array, callback, thisArg) {
if (typeof callback != 'number' && callback != null) {
var n = 0,
index = -1,
length = array ? array.length : 0;
callback = createCallback(callback, thisArg, 3);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
}
return slice(array, n);
}
module.exports = rest;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
identity = require('../utilities/identity');
/**
* Uses a binary search to determine the smallest index at which a value
* should be inserted into a given sorted array in order to maintain the sort
* order of the array. If a callback is provided it will be executed for
* `value` and each element of `array` to compute their sort ranking. The
* callback is bound to `thisArg` and invoked with one argument; (value).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to inspect.
* @param {*} value The value to evaluate.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
* @example
*
* _.sortedIndex([20, 30, 50], 40);
* // => 2
*
* // using "_.pluck" callback shorthand
* _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
* // => 2
*
* var dict = {
* 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
* };
*
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return dict.wordToNumber[word];
* });
* // => 2
*
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return this.wordToNumber[word];
* }, dict);
* // => 2
*/
function sortedIndex(array, value, callback, thisArg) {
var low = 0,
high = array ? array.length : low;
// explicitly reference `identity` for better inlining in Firefox
callback = callback ? createCallback(callback, thisArg, 1) : identity;
value = callback(value);
while (low < high) {
var mid = (low + high) >>> 1;
(callback(array[mid]) < value)
? low = mid + 1
: high = mid;
}
return low;
}
module.exports = sortedIndex;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseFlatten = require('../internals/baseFlatten'),
baseUniq = require('../internals/baseUniq');
/**
* Creates an array of unique values, in order, of the provided arrays using
* strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of combined values.
* @example
*
* _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
* // => [1, 2, 3, 5, 4]
*/
function union() {
return baseUniq(baseFlatten(arguments, true, true));
}
module.exports = union;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseUniq = require('../internals/baseUniq'),
createCallback = require('../functions/createCallback');
/**
* Creates a duplicate-value-free version of an array using strict equality
* for comparisons, i.e. `===`. If the array is sorted, providing
* `true` for `isSorted` will use a faster algorithm. If a callback is provided
* each element of `array` is passed through the callback before uniqueness
* is computed. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias unique
* @category Arrays
* @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a duplicate-value-free array.
* @example
*
* _.uniq([1, 2, 1, 3, 1]);
* // => [1, 2, 3]
*
* _.uniq([1, 1, 2, 2, 3], true);
* // => [1, 2, 3]
*
* _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
* // => ['A', 'b', 'C']
*
* _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
* // => [1, 2.5, 3]
*
* // using "_.pluck" callback shorthand
* _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
function uniq(array, isSorted, callback, thisArg) {
// juggle arguments
if (typeof isSorted != 'boolean' && isSorted != null) {
thisArg = callback;
callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
isSorted = false;
}
if (callback != null) {
callback = createCallback(callback, thisArg, 3);
}
return baseUniq(array, isSorted, callback);
}
module.exports = uniq;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseDifference = require('../internals/baseDifference'),
slice = require('../internals/slice');
/**
* Creates an array excluding all provided values using strict equality for
* comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to filter.
* @param {...*} [value] The values to exclude.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
* // => [2, 3, 4]
*/
function without(array) {
return baseDifference(array, slice(arguments, 1));
}
module.exports = without;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseDifference = require('../internals/baseDifference'),
baseUniq = require('../internals/baseUniq'),
isArguments = require('../objects/isArguments'),
isArray = require('../objects/isArray');
/**
* Creates an array that is the symmetric difference of the provided arrays.
* See http://en.wikipedia.org/wiki/Symmetric_difference.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of values.
* @example
*
* _.xor([1, 2, 3], [5, 2, 1, 4]);
* // => [3, 5, 4]
*
* _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
* // => [1, 4, 5]
*/
function xor() {
var index = -1,
length = arguments.length;
while (++index < length) {
var array = arguments[index];
if (isArray(array) || isArguments(array)) {
var result = result
? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
: array;
}
}
return result || [];
}
module.exports = xor;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var max = require('../collections/max'),
pluck = require('../collections/pluck');
/**
* Creates an array of grouped elements, the first of which contains the first
* elements of the given arrays, the second of which contains the second
* elements of the given arrays, and so on.
*
* @static
* @memberOf _
* @alias unzip
* @category Arrays
* @param {...Array} [array] Arrays to process.
* @returns {Array} Returns a new array of grouped elements.
* @example
*
* _.zip(['fred', 'barney'], [30, 40], [true, false]);
* // => [['fred', 30, true], ['barney', 40, false]]
*/
function zip() {
var array = arguments.length > 1 ? arguments : arguments[0],
index = -1,
length = array ? max(pluck(array, 'length')) : 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = pluck(array, index);
}
return result;
}
module.exports = zip;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isArray = require('../objects/isArray');
/**
* Creates an object composed from arrays of `keys` and `values`. Provide
* either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
* or two arrays, one of `keys` and one of corresponding `values`.
*
* @static
* @memberOf _
* @alias object
* @category Arrays
* @param {Array} keys The array of keys.
* @param {Array} [values=[]] The array of values.
* @returns {Object} Returns an object composed of the given keys and
* corresponding values.
* @example
*
* _.zipObject(['fred', 'barney'], [30, 40]);
* // => { 'fred': 30, 'barney': 40 }
*/
function zipObject(keys, values) {
var index = -1,
length = keys ? keys.length : 0,
result = {};
if (!values && length && !isArray(keys[0])) {
values = [];
}
while (++index < length) {
var key = keys[index];
if (values) {
result[key] = values[index];
} else if (key) {
result[key[0]] = key[1];
}
}
return result;
}
module.exports = zipObject;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| chain.js | 50% | (3 / 6) | 100% | (0 / 0) | 0% | (0 / 1) | 50% | (3 / 6) | |
| tap.js | 50% | (2 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 50% | (2 / 4) | |
| wrapperChain.js | 50% | (2 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 50% | (2 / 4) | |
| wrapperToString.js | 66.67% | (2 / 3) | 100% | (0 / 0) | 0% | (0 / 1) | 66.67% | (2 / 3) | |
| wrapperValueOf.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var lodashWrapper = require('../internals/lodashWrapper');
/**
* Creates a `lodash` object that wraps the given value with explicit
* method chaining enabled.
*
* @static
* @memberOf _
* @category Chaining
* @param {*} value The value to wrap.
* @returns {Object} Returns the wrapper object.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 },
* { 'name': 'pebbles', 'age': 1 }
* ];
*
* var youngest = _.chain(characters)
* .sortBy('age')
* .map(function(chr) { return chr.name + ' is ' + chr.age; })
* .first()
* .value();
* // => 'pebbles is 1'
*/
function chain(value) {
value = new lodashWrapper(value);
value.__chain__ = true;
return value;
}
module.exports = chain;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Invokes `interceptor` with the `value` as the first argument and then
* returns `value`. The purpose of this method is to "tap into" a method
* chain in order to perform operations on intermediate results within
* the chain.
*
* @static
* @memberOf _
* @category Chaining
* @param {*} value The value to provide to `interceptor`.
* @param {Function} interceptor The function to invoke.
* @returns {*} Returns `value`.
* @example
*
* _([1, 2, 3, 4])
* .tap(function(array) { array.pop(); })
* .reverse()
* .value();
* // => [3, 2, 1]
*/
function tap(value, interceptor) {
interceptor(value);
return value;
}
module.exports = tap;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Enables explicit method chaining on the wrapper object.
*
* @name chain
* @memberOf _
* @category Chaining
* @returns {*} Returns the wrapper object.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // without explicit chaining
* _(characters).first();
* // => { 'name': 'barney', 'age': 36 }
*
* // with explicit chaining
* _(characters).chain()
* .first()
* .pick('age')
* .value();
* // => { 'age': 36 }
*/
function wrapperChain() {
this.__chain__ = true;
return this;
}
module.exports = wrapperChain;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Produces the `toString` result of the wrapped value.
*
* @name toString
* @memberOf _
* @category Chaining
* @returns {string} Returns the string result.
* @example
*
* _([1, 2, 3]).toString();
* // => '1,2,3'
*/
function wrapperToString() {
return String(this.__wrapped__);
}
module.exports = wrapperToString;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var forEach = require('../collections/forEach'),
support = require('../support');
/**
* Extracts the wrapped value.
*
* @name valueOf
* @memberOf _
* @alias value
* @category Chaining
* @returns {*} Returns the wrapped value.
* @example
*
* _([1, 2, 3]).valueOf();
* // => [1, 2, 3]
*/
function wrapperValueOf() {
return this.__wrapped__;
}
module.exports = wrapperValueOf;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| at.js | 42.86% | (3 / 7) | 0% | (0 / 4) | 0% | (0 / 1) | 42.86% | (3 / 7) | |
| contains.js | 28.57% | (4 / 14) | 0% | (0 / 14) | 0% | (0 / 2) | 28.57% | (4 / 14) | |
| countBy.js | 83.33% | (5 / 6) | 0% | (0 / 2) | 0% | (0 / 1) | 83.33% | (5 / 6) | |
| every.js | 23.08% | (3 / 13) | 0% | (0 / 6) | 0% | (0 / 2) | 23.08% | (3 / 13) | |
| filter.js | 20% | (3 / 15) | 0% | (0 / 8) | 0% | (0 / 2) | 20% | (3 / 15) | |
| find.js | 18.75% | (3 / 16) | 0% | (0 / 8) | 0% | (0 / 2) | 18.75% | (3 / 16) | |
| findLast.js | 30% | (3 / 10) | 0% | (0 / 2) | 0% | (0 / 2) | 30% | (3 / 10) | |
| forEach.js | 81.82% | (9 / 11) | 60% | (6 / 10) | 100% | (1 / 1) | 81.82% | (9 / 11) | |
| forEachRight.js | 20% | (3 / 15) | 0% | (0 / 12) | 0% | (0 / 2) | 20% | (3 / 15) | |
| groupBy.js | 83.33% | (5 / 6) | 0% | (0 / 2) | 0% | (0 / 1) | 83.33% | (5 / 6) | |
| indexBy.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| invoke.js | 42.86% | (3 / 7) | 0% | (0 / 6) | 0% | (0 / 2) | 42.86% | (3 / 7) | |
| map.js | 23.08% | (3 / 13) | 0% | (0 / 4) | 0% | (0 / 2) | 23.08% | (3 / 13) | |
| max.js | 15.79% | (3 / 19) | 0% | (0 / 17) | 0% | (0 / 2) | 15.79% | (3 / 19) | |
| min.js | 15.79% | (3 / 19) | 0% | (0 / 17) | 0% | (0 / 2) | 15.79% | (3 / 19) | |
| pluck.js | 100% | (3 / 3) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (3 / 3) | |
| reduce.js | 18.75% | (3 / 16) | 0% | (0 / 8) | 0% | (0 / 2) | 20% | (3 / 15) | |
| reduceRight.js | 37.5% | (3 / 8) | 0% | (0 / 2) | 0% | (0 / 2) | 37.5% | (3 / 8) | |
| reject.js | 50% | (3 / 6) | 100% | (0 / 0) | 0% | (0 / 2) | 50% | (3 / 6) | |
| sample.js | 36.36% | (4 / 11) | 0% | (0 / 10) | 0% | (0 / 1) | 36.36% | (4 / 11) | |
| shuffle.js | 33.33% | (3 / 9) | 0% | (0 / 4) | 0% | (0 / 2) | 33.33% | (3 / 9) | |
| size.js | 60% | (3 / 5) | 0% | (0 / 4) | 0% | (0 / 1) | 60% | (3 / 5) | |
| some.js | 23.08% | (3 / 13) | 0% | (0 / 6) | 0% | (0 / 2) | 23.08% | (3 / 13) | |
| sortBy.js | 13.04% | (3 / 23) | 0% | (0 / 10) | 0% | (0 / 3) | 13.64% | (3 / 22) | |
| toArray.js | 50% | (3 / 6) | 0% | (0 / 4) | 0% | (0 / 1) | 50% | (3 / 6) | |
| where.js | 100% | (3 / 3) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (3 / 3) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseFlatten = require('../internals/baseFlatten'),
isString = require('../objects/isString');
/**
* Creates an array of elements from the specified indexes, or keys, of the
* `collection`. Indexes may be specified as individual arguments or as arrays
* of indexes.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
* to retrieve, specified as individual indexes or arrays of indexes.
* @returns {Array} Returns a new array of elements corresponding to the
* provided indexes.
* @example
*
* _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
* // => ['a', 'c', 'e']
*
* _.at(['fred', 'barney', 'pebbles'], 0, 2);
* // => ['fred', 'pebbles']
*/
function at(collection) {
var args = arguments,
index = -1,
props = baseFlatten(args, true, false, 1),
length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
result = Array(length);
while(++index < length) {
result[index] = collection[props[index]];
}
return result;
}
module.exports = at;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseIndexOf = require('../internals/baseIndexOf'),
forOwn = require('../objects/forOwn'),
isArray = require('../objects/isArray'),
isString = require('../objects/isString');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max;
/**
* Checks if a given value is present in a collection using strict equality
* for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
* offset from the end of the collection.
*
* @static
* @memberOf _
* @alias include
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {*} target The value to check for.
* @param {number} [fromIndex=0] The index to search from.
* @returns {boolean} Returns `true` if the `target` element is found, else `false`.
* @example
*
* _.contains([1, 2, 3], 1);
* // => true
*
* _.contains([1, 2, 3], 1, 2);
* // => false
*
* _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
* // => true
*
* _.contains('pebbles', 'eb');
* // => true
*/
function contains(collection, target, fromIndex) {
var index = -1,
indexOf = baseIndexOf,
length = collection ? collection.length : 0,
result = false;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
if (isArray(collection)) {
result = indexOf(collection, target, fromIndex) > -1;
} else if (typeof length == 'number') {
result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
} else {
forOwn(collection, function(value) {
if (++index >= fromIndex) {
return !(result = value === target);
}
});
}
return result;
}
module.exports = contains;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createAggregator = require('../internals/createAggregator');
/** Used for native method references */
var objectProto = Object.prototype;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Creates an object composed of keys generated from the results of running
* each element of `collection` through the callback. The corresponding value
* of each key is the number of times the key was returned by the callback.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
* // => { '4': 1, '6': 2 }
*
* _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': 1, '6': 2 }
*
* _.countBy(['one', 'two', 'three'], 'length');
* // => { '3': 2, '5': 1 }
*/
var countBy = createAggregator(function(result, value, key) {
(hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
});
module.exports = countBy;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('../objects/forOwn');
/**
* Checks if the given callback returns truey value for **all** elements of
* a collection. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias all
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if all elements passed the callback check,
* else `false`.
* @example
*
* _.every([true, 1, null, 'yes']);
* // => false
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // using "_.pluck" callback shorthand
* _.every(characters, 'age');
* // => true
*
* // using "_.where" callback shorthand
* _.every(characters, { 'age': 36 });
* // => false
*/
function every(collection, callback, thisArg) {
var result = true;
callback = createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
if (!(result = !!callback(collection[index], index, collection))) {
break;
}
}
} else {
forOwn(collection, function(value, index, collection) {
return (result = !!callback(value, index, collection));
});
}
return result;
}
module.exports = every;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('../objects/forOwn');
/**
* Iterates over elements of a collection, returning an array of all elements
* the callback returns truey for. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias select
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that passed the callback check.
* @example
*
* var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [2, 4, 6]
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.filter(characters, 'blocked');
* // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
*
* // using "_.where" callback shorthand
* _.filter(characters, { 'age': 36 });
* // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
*/
function filter(collection, callback, thisArg) {
var result = [];
callback = createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
if (callback(value, index, collection)) {
result.push(value);
}
}
} else {
forOwn(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result.push(value);
}
});
}
return result;
}
module.exports = filter;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('../objects/forOwn');
/**
* Iterates over elements of a collection, returning the first element that
* the callback returns truey for. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias detect, findWhere
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the found element, else `undefined`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true },
* { 'name': 'pebbles', 'age': 1, 'blocked': false }
* ];
*
* _.find(characters, function(chr) {
* return chr.age < 40;
* });
* // => { 'name': 'barney', 'age': 36, 'blocked': false }
*
* // using "_.where" callback shorthand
* _.find(characters, { 'age': 1 });
* // => { 'name': 'pebbles', 'age': 1, 'blocked': false }
*
* // using "_.pluck" callback shorthand
* _.find(characters, 'blocked');
* // => { 'name': 'fred', 'age': 40, 'blocked': true }
*/
function find(collection, callback, thisArg) {
callback = createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
if (callback(value, index, collection)) {
return value;
}
}
} else {
var result;
forOwn(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result = value;
return false;
}
});
return result;
}
}
module.exports = find;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forEachRight = require('./forEachRight');
/**
* This method is like `_.find` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the found element, else `undefined`.
* @example
*
* _.findLast([1, 2, 3, 4], function(num) {
* return num % 2 == 1;
* });
* // => 3
*/
function findLast(collection, callback, thisArg) {
var result;
callback = createCallback(callback, thisArg, 3);
forEachRight(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result = value;
return false;
}
});
return result;
}
module.exports = findLast;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 1 1 5 5 5 5 146 5 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
forOwn = require('../objects/forOwn');
/**
* Iterates over elements of a collection, executing the callback for each
* element. The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection). Callbacks may exit iteration early by
* explicitly returning `false`.
*
* Note: As with other "Collections" methods, objects with a `length` property
* are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
* may be used for object iteration.
*
* @static
* @memberOf _
* @alias each
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array|Object|string} Returns `collection`.
* @example
*
* _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
* // => logs each number and returns '1,2,3'
*
* _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
* // => logs each number and returns the object (property order is not guaranteed across environments)
*/
function forEach(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
Eif (typeof length == 'number') {
while (++index < length) {
Iif (callback(collection[index], index, collection) === false) {
break;
}
}
} else {
forOwn(collection, callback);
}
return collection;
}
module.exports = forEach;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
forOwn = require('../objects/forOwn'),
isArray = require('../objects/isArray'),
isString = require('../objects/isString'),
keys = require('../objects/keys');
/**
* This method is like `_.forEach` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @alias eachRight
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array|Object|string} Returns `collection`.
* @example
*
* _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
* // => logs each number from right to left and returns '3,2,1'
*/
function forEachRight(collection, callback, thisArg) {
var length = collection ? collection.length : 0;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
if (typeof length == 'number') {
while (length--) {
if (callback(collection[length], length, collection) === false) {
break;
}
}
} else {
var props = keys(collection);
length = props.length;
forOwn(collection, function(value, key, collection) {
key = props ? props[--length] : --length;
return callback(collection[key], key, collection);
});
}
return collection;
}
module.exports = forEachRight;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createAggregator = require('../internals/createAggregator');
/** Used for native method references */
var objectProto = Object.prototype;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Creates an object composed of keys generated from the results of running
* each element of a collection through the callback. The corresponding value
* of each key is an array of the elements responsible for generating the key.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
* // using "_.pluck" callback shorthand
* _.groupBy(['one', 'two', 'three'], 'length');
* // => { '3': ['one', 'two'], '5': ['three'] }
*/
var groupBy = createAggregator(function(result, value, key) {
(hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
});
module.exports = groupBy;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createAggregator = require('../internals/createAggregator');
/**
* Creates an object composed of keys generated from the results of running
* each element of the collection through the given callback. The corresponding
* value of each key is the last element responsible for generating the key.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* var keys = [
* { 'dir': 'left', 'code': 97 },
* { 'dir': 'right', 'code': 100 }
* ];
*
* _.indexBy(keys, 'dir');
* // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
*
* _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*
* _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*/
var indexBy = createAggregator(function(result, value, key) {
result[key] = value;
});
module.exports = indexBy;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var forEach = require('./forEach'),
slice = require('../internals/slice');
/**
* Invokes the method named by `methodName` on each element in the `collection`
* returning an array of the results of each invoked method. Additional arguments
* will be provided to each invoked method. If `methodName` is a function it
* will be invoked for, and `this` bound to, each element in the `collection`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|string} methodName The name of the method to invoke or
* the function invoked per iteration.
* @param {...*} [arg] Arguments to invoke the method with.
* @returns {Array} Returns a new array of the results of each invoked method.
* @example
*
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
* // => [[1, 5, 7], [1, 2, 3]]
*
* _.invoke([123, 456], String.prototype.split, '');
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
function invoke(collection, methodName) {
var args = slice(arguments, 2),
index = -1,
isFunc = typeof methodName == 'function',
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
forEach(collection, function(value) {
result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
});
return result;
}
module.exports = invoke;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('../objects/forOwn');
/**
* Creates an array of values by running each element in the collection
* through the callback. The callback is bound to `thisArg` and invoked with
* three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias collect
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of the results of each `callback` execution.
* @example
*
* _.map([1, 2, 3], function(num) { return num * 3; });
* // => [3, 6, 9]
*
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
* // => [3, 6, 9] (property order is not guaranteed across environments)
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // using "_.pluck" callback shorthand
* _.map(characters, 'name');
* // => ['barney', 'fred']
*/
function map(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0;
callback = createCallback(callback, thisArg, 3);
if (typeof length == 'number') {
var result = Array(length);
while (++index < length) {
result[index] = callback(collection[index], index, collection);
}
} else {
result = [];
forOwn(collection, function(value, key, collection) {
result[++index] = callback(value, key, collection);
});
}
return result;
}
module.exports = map;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var charAtCallback = require('../internals/charAtCallback'),
createCallback = require('../functions/createCallback'),
forEach = require('./forEach'),
forOwn = require('../objects/forOwn'),
isArray = require('../objects/isArray'),
isString = require('../objects/isString');
/**
* Retrieves the maximum value of a collection. If the collection is empty or
* falsey `-Infinity` is returned. If a callback is provided it will be executed
* for each value in the collection to generate the criterion by which the value
* is ranked. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the maximum value.
* @example
*
* _.max([4, 2, 8, 6]);
* // => 8
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.max(characters, function(chr) { return chr.age; });
* // => { 'name': 'fred', 'age': 40 };
*
* // using "_.pluck" callback shorthand
* _.max(characters, 'age');
* // => { 'name': 'fred', 'age': 40 };
*/
function max(collection, callback, thisArg) {
var computed = -Infinity,
result = computed;
// allows working with functions like `_.map` without using
// their `index` argument as a callback
if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
callback = null;
}
if (callback == null && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
if (value > result) {
result = value;
}
}
} else {
callback = (callback == null && isString(collection))
? charAtCallback
: createCallback(callback, thisArg, 3);
forEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
if (current > computed) {
computed = current;
result = value;
}
});
}
return result;
}
module.exports = max;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var charAtCallback = require('../internals/charAtCallback'),
createCallback = require('../functions/createCallback'),
forEach = require('./forEach'),
forOwn = require('../objects/forOwn'),
isArray = require('../objects/isArray'),
isString = require('../objects/isString');
/**
* Retrieves the minimum value of a collection. If the collection is empty or
* falsey `Infinity` is returned. If a callback is provided it will be executed
* for each value in the collection to generate the criterion by which the value
* is ranked. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the minimum value.
* @example
*
* _.min([4, 2, 8, 6]);
* // => 2
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.min(characters, function(chr) { return chr.age; });
* // => { 'name': 'barney', 'age': 36 };
*
* // using "_.pluck" callback shorthand
* _.min(characters, 'age');
* // => { 'name': 'barney', 'age': 36 };
*/
function min(collection, callback, thisArg) {
var computed = Infinity,
result = computed;
// allows working with functions like `_.map` without using
// their `index` argument as a callback
if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
callback = null;
}
if (callback == null && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
if (value < result) {
result = value;
}
}
} else {
callback = (callback == null && isString(collection))
? charAtCallback
: createCallback(callback, thisArg, 3);
forEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
if (current < computed) {
computed = current;
result = value;
}
});
}
return result;
}
module.exports = min;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var map = require('./map');
/**
* Retrieves the value of a specified property from all elements in the collection.
*
* @static
* @memberOf _
* @type Function
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {string} property The name of the property to pluck.
* @returns {Array} Returns a new array of property values.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.pluck(characters, 'name');
* // => ['barney', 'fred']
*/
var pluck = map;
module.exports = pluck;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('../objects/forOwn');
/**
* Reduces a collection to a value which is the accumulated result of running
* each element in the collection through the callback, where each successive
* callback execution consumes the return value of the previous execution. If
* `accumulator` is not provided the first element of the collection will be
* used as the initial `accumulator` value. The callback is bound to `thisArg`
* and invoked with four arguments; (accumulator, value, index|key, collection).
*
* @static
* @memberOf _
* @alias foldl, inject
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] Initial value of the accumulator.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var sum = _.reduce([1, 2, 3], function(sum, num) {
* return sum + num;
* });
* // => 6
*
* var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
* result[key] = num * 3;
* return result;
* }, {});
* // => { 'a': 3, 'b': 6, 'c': 9 }
*/
function reduce(collection, callback, accumulator, thisArg) {
if (!collection) return accumulator;
var noaccum = arguments.length < 3;
callback = createCallback(callback, thisArg, 4);
var index = -1,
length = collection.length;
if (typeof length == 'number') {
if (noaccum) {
accumulator = collection[++index];
}
while (++index < length) {
accumulator = callback(accumulator, collection[index], index, collection);
}
} else {
forOwn(collection, function(value, index, collection) {
accumulator = noaccum
? (noaccum = false, value)
: callback(accumulator, value, index, collection)
});
}
return accumulator;
}
module.exports = reduce;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forEachRight = require('./forEachRight');
/**
* This method is like `_.reduce` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @alias foldr
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] Initial value of the accumulator.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var list = [[0, 1], [2, 3], [4, 5]];
* var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
* // => [4, 5, 2, 3, 0, 1]
*/
function reduceRight(collection, callback, accumulator, thisArg) {
var noaccum = arguments.length < 3;
callback = createCallback(callback, thisArg, 4);
forEachRight(collection, function(value, index, collection) {
accumulator = noaccum
? (noaccum = false, value)
: callback(accumulator, value, index, collection);
});
return accumulator;
}
module.exports = reduceRight;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
filter = require('./filter');
/**
* The opposite of `_.filter` this method returns the elements of a
* collection that the callback does **not** return truey for.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that failed the callback check.
* @example
*
* var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [1, 3, 5]
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.reject(characters, 'blocked');
* // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
*
* // using "_.where" callback shorthand
* _.reject(characters, { 'age': 36 });
* // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
*/
function reject(collection, callback, thisArg) {
callback = createCallback(callback, thisArg, 3);
return filter(collection, function(value, index, collection) {
return !callback(value, index, collection);
});
}
module.exports = reject;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseRandom = require('../internals/baseRandom'),
isString = require('../objects/isString'),
shuffle = require('./shuffle'),
values = require('../objects/values');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max,
nativeMin = Math.min;
/**
* Retrieves a random element or `n` random elements from a collection.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to sample.
* @param {number} [n] The number of elements to sample.
* @param- {Object} [guard] Allows working with functions like `_.map`
* without using their `index` arguments as `n`.
* @returns {Array} Returns the random sample(s) of `collection`.
* @example
*
* _.sample([1, 2, 3, 4]);
* // => 2
*
* _.sample([1, 2, 3, 4], 2);
* // => [3, 1]
*/
function sample(collection, n, guard) {
if (collection && typeof collection.length != 'number') {
collection = values(collection);
}
if (n == null || guard) {
return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
}
var result = shuffle(collection);
result.length = nativeMin(nativeMax(0, n), result.length);
return result;
}
module.exports = sample;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseRandom = require('../internals/baseRandom'),
forEach = require('./forEach');
/**
* Creates an array of shuffled values, using a version of the Fisher-Yates
* shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to shuffle.
* @returns {Array} Returns a new shuffled collection.
* @example
*
* _.shuffle([1, 2, 3, 4, 5, 6]);
* // => [4, 1, 6, 3, 5, 2]
*/
function shuffle(collection) {
var index = -1,
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
forEach(collection, function(value) {
var rand = baseRandom(0, ++index);
result[index] = result[rand];
result[rand] = value;
});
return result;
}
module.exports = shuffle;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var keys = require('../objects/keys');
/**
* Gets the size of the `collection` by returning `collection.length` for arrays
* and array-like objects or the number of own enumerable properties for objects.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to inspect.
* @returns {number} Returns `collection.length` or number of own enumerable properties.
* @example
*
* _.size([1, 2]);
* // => 2
*
* _.size({ 'one': 1, 'two': 2, 'three': 3 });
* // => 3
*
* _.size('pebbles');
* // => 7
*/
function size(collection) {
var length = collection ? collection.length : 0;
return typeof length == 'number' ? length : keys(collection).length;
}
module.exports = size;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('../objects/forOwn'),
isArray = require('../objects/isArray');
/**
* Checks if the callback returns a truey value for **any** element of a
* collection. The function returns as soon as it finds a passing value and
* does not iterate over the entire collection. The callback is bound to
* `thisArg` and invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias any
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if any element passed the callback check,
* else `false`.
* @example
*
* _.some([null, 0, 'yes', false], Boolean);
* // => true
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.some(characters, 'blocked');
* // => true
*
* // using "_.where" callback shorthand
* _.some(characters, { 'age': 1 });
* // => false
*/
function some(collection, callback, thisArg) {
var result;
callback = createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
if ((result = callback(collection[index], index, collection))) {
break;
}
}
} else {
forOwn(collection, function(value, index, collection) {
return !(result = callback(value, index, collection));
});
}
return !!result;
}
module.exports = some;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var compareAscending = require('../internals/compareAscending'),
createCallback = require('../functions/createCallback'),
forEach = require('./forEach'),
getArray = require('../internals/getArray'),
getObject = require('../internals/getObject'),
isArray = require('../objects/isArray'),
map = require('./map'),
releaseArray = require('../internals/releaseArray'),
releaseObject = require('../internals/releaseObject');
/**
* Creates an array of elements, sorted in ascending order by the results of
* running each element in a collection through the callback. This method
* performs a stable sort, that is, it will preserve the original sort order
* of equal elements. The callback is bound to `thisArg` and invoked with
* three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an array of property names is provided for `callback` the collection
* will be sorted by each property value.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Array|Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of sorted elements.
* @example
*
* _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
* // => [3, 1, 2]
*
* _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
* // => [3, 1, 2]
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 },
* { 'name': 'barney', 'age': 26 },
* { 'name': 'fred', 'age': 30 }
* ];
*
* // using "_.pluck" callback shorthand
* _.map(_.sortBy(characters, 'age'), _.values);
* // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
*
* // sorting by multiple properties
* _.map(_.sortBy(characters, ['name', 'age']), _.values);
* // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
*/
function sortBy(collection, callback, thisArg) {
var index = -1,
isArr = isArray(callback),
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
if (!isArr) {
callback = createCallback(callback, thisArg, 3);
}
forEach(collection, function(value, key, collection) {
var object = result[++index] = getObject();
if (isArr) {
object.criteria = map(callback, function(key) { return value[key]; });
} else {
(object.criteria = getArray())[0] = callback(value, key, collection);
}
object.index = index;
object.value = value;
});
length = result.length;
result.sort(compareAscending);
while (length--) {
var object = result[length];
result[length] = object.value;
if (!isArr) {
releaseArray(object.criteria);
}
releaseObject(object);
}
return result;
}
module.exports = sortBy;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isString = require('../objects/isString'),
slice = require('../internals/slice'),
values = require('../objects/values');
/**
* Converts the `collection` to an array.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to convert.
* @returns {Array} Returns the new converted array.
* @example
*
* (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
* // => [2, 3, 4]
*/
function toArray(collection) {
if (collection && typeof collection.length == 'number') {
return slice(collection);
}
return values(collection);
}
module.exports = toArray;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var filter = require('./filter');
/**
* Performs a deep comparison of each element in a `collection` to the given
* `properties` object, returning an array of all elements that have equivalent
* property values.
*
* @static
* @memberOf _
* @type Function
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Object} props The object of property values to filter by.
* @returns {Array} Returns a new array of elements that have the given properties.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
* { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
* ];
*
* _.where(characters, { 'age': 36 });
* // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
*
* _.where(characters, { 'pets': ['dino'] });
* // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
*/
var where = filter;
module.exports = where;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| after.js | 37.5% | (3 / 8) | 0% | (0 / 4) | 0% | (0 / 2) | 37.5% | (3 / 8) | |
| bind.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| bindAll.js | 37.5% | (3 / 8) | 0% | (0 / 2) | 0% | (0 / 1) | 37.5% | (3 / 8) | |
| bindKey.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| compose.js | 25% | (3 / 12) | 0% | (0 / 2) | 0% | (0 / 2) | 25% | (3 / 12) | |
| createCallback.js | 15.79% | (3 / 19) | 0% | (0 / 16) | 0% | (0 / 3) | 15.79% | (3 / 19) | |
| curry.js | 60% | (3 / 5) | 0% | (0 / 4) | 0% | (0 / 1) | 60% | (3 / 5) | |
| debounce.js | 6.25% | (4 / 64) | 0% | (0 / 65) | 0% | (0 / 4) | 6.25% | (4 / 64) | |
| defer.js | 37.5% | (3 / 8) | 0% | (0 / 2) | 0% | (0 / 2) | 42.86% | (3 / 7) | |
| delay.js | 37.5% | (3 / 8) | 0% | (0 / 2) | 0% | (0 / 2) | 42.86% | (3 / 7) | |
| memoize.js | 41.67% | (5 / 12) | 0% | (0 / 6) | 0% | (0 / 2) | 41.67% | (5 / 12) | |
| once.js | 23.08% | (3 / 13) | 0% | (0 / 4) | 0% | (0 / 2) | 23.08% | (3 / 13) | |
| partial.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| partialRight.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| throttle.js | 25% | (4 / 16) | 0% | (0 / 10) | 0% | (0 / 1) | 25% | (4 / 16) | |
| wrap.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isFunction = require('../objects/isFunction');
/**
* Creates a function that executes `func`, with the `this` binding and
* arguments of the created function, only after being called `n` times.
*
* @static
* @memberOf _
* @category Functions
* @param {number} n The number of times the function must be called before
* `func` is executed.
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var saves = ['profile', 'settings'];
*
* var done = _.after(saves.length, function() {
* console.log('Done saving!');
* });
*
* _.forEach(saves, function(type) {
* asyncSave({ 'type': type, 'complete': done });
* });
* // => logs 'Done saving!', after all saves have completed
*/
function after(n, func) {
if (!isFunction(func)) {
throw new TypeError;
}
return function() {
if (--n < 1) {
return func.apply(this, arguments);
}
};
}
module.exports = after;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createWrapper = require('../internals/createWrapper'),
slice = require('../internals/slice');
/**
* Creates a function that, when called, invokes `func` with the `this`
* binding of `thisArg` and prepends any additional `bind` arguments to those
* provided to the bound function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to bind.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var func = function(greeting) {
* return greeting + ' ' + this.name;
* };
*
* func = _.bind(func, { 'name': 'fred' }, 'hi');
* func();
* // => 'hi fred'
*/
function bind(func, thisArg) {
return arguments.length > 2
? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
: createWrapper(func, 1, null, null, thisArg);
}
module.exports = bind;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseFlatten = require('../internals/baseFlatten'),
createWrapper = require('../internals/createWrapper'),
functions = require('../objects/functions');
/**
* Binds methods of an object to the object itself, overwriting the existing
* method. Method names may be specified as individual arguments or as arrays
* of method names. If no method names are provided all the function properties
* of `object` will be bound.
*
* @static
* @memberOf _
* @category Functions
* @param {Object} object The object to bind and assign the bound methods to.
* @param {...string} [methodName] The object method names to
* bind, specified as individual method names or arrays of method names.
* @returns {Object} Returns `object`.
* @example
*
* var view = {
* 'label': 'docs',
* 'onClick': function() { console.log('clicked ' + this.label); }
* };
*
* _.bindAll(view);
* jQuery('#docs').on('click', view.onClick);
* // => logs 'clicked docs', when the button is clicked
*/
function bindAll(object) {
var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
index = -1,
length = funcs.length;
while (++index < length) {
var key = funcs[index];
object[key] = createWrapper(object[key], 1, null, null, object);
}
return object;
}
module.exports = bindAll;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createWrapper = require('../internals/createWrapper'),
slice = require('../internals/slice');
/**
* Creates a function that, when called, invokes the method at `object[key]`
* and prepends any additional `bindKey` arguments to those provided to the bound
* function. This method differs from `_.bind` by allowing bound functions to
* reference methods that will be redefined or don't yet exist.
* See http://michaux.ca/articles/lazy-function-definition-pattern.
*
* @static
* @memberOf _
* @category Functions
* @param {Object} object The object the method belongs to.
* @param {string} key The key of the method.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var object = {
* 'name': 'fred',
* 'greet': function(greeting) {
* return greeting + ' ' + this.name;
* }
* };
*
* var func = _.bindKey(object, 'greet', 'hi');
* func();
* // => 'hi fred'
*
* object.greet = function(greeting) {
* return greeting + 'ya ' + this.name + '!';
* };
*
* func();
* // => 'hiya fred!'
*/
function bindKey(object, key) {
return arguments.length > 2
? createWrapper(key, 19, slice(arguments, 2), null, object)
: createWrapper(key, 3, null, null, object);
}
module.exports = bindKey;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isFunction = require('../objects/isFunction');
/**
* Creates a function that is the composition of the provided functions,
* where each function consumes the return value of the function that follows.
* For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
* Each function is executed with the `this` binding of the composed function.
*
* @static
* @memberOf _
* @category Functions
* @param {...Function} [func] Functions to compose.
* @returns {Function} Returns the new composed function.
* @example
*
* var realNameMap = {
* 'pebbles': 'penelope'
* };
*
* var format = function(name) {
* name = realNameMap[name.toLowerCase()] || name;
* return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
* };
*
* var greet = function(formatted) {
* return 'Hiya ' + formatted + '!';
* };
*
* var welcome = _.compose(greet, format);
* welcome('pebbles');
* // => 'Hiya Penelope!'
*/
function compose() {
var funcs = arguments,
length = funcs.length;
while (length--) {
if (!isFunction(funcs[length])) {
throw new TypeError;
}
}
return function() {
var args = arguments,
length = funcs.length;
while (length--) {
args = [funcs[length].apply(this, args)];
}
return args[0];
};
}
module.exports = compose;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
baseIsEqual = require('../internals/baseIsEqual'),
isObject = require('../objects/isObject'),
keys = require('../objects/keys'),
property = require('../utilities/property');
/**
* Produces a callback bound to an optional `thisArg`. If `func` is a property
* name the created callback will return the property value for a given element.
* If `func` is an object the created callback will return `true` for elements
* that contain the equivalent object properties, otherwise it will return `false`.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} [func=identity] The value to convert to a callback.
* @param {*} [thisArg] The `this` binding of the created callback.
* @param {number} [argCount] The number of arguments the callback accepts.
* @returns {Function} Returns a callback function.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // wrap to create custom callback shorthands
* _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
* var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
* return !match ? func(callback, thisArg) : function(object) {
* return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
* };
* });
*
* _.filter(characters, 'age__gt38');
* // => [{ 'name': 'fred', 'age': 40 }]
*/
function createCallback(func, thisArg, argCount) {
var type = typeof func;
if (func == null || type == 'function') {
return baseCreateCallback(func, thisArg, argCount);
}
// handle "_.pluck" style callback shorthands
if (type != 'object') {
return property(func);
}
var props = keys(func),
key = props[0],
a = func[key];
// handle "_.where" style callback shorthands
if (props.length == 1 && a === a && !isObject(a)) {
// fast path the common case of providing an object with a single
// property containing a primitive value
return function(object) {
var b = object[key];
return a === b && (a !== 0 || (1 / a == 1 / b));
};
}
return function(object) {
var length = props.length,
result = false;
while (length--) {
if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
break;
}
}
return result;
};
}
module.exports = createCallback;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createWrapper = require('../internals/createWrapper');
/**
* Creates a function which accepts one or more arguments of `func` that when
* invoked either executes `func` returning its result, if all `func` arguments
* have been provided, or returns a function that accepts one or more of the
* remaining `func` arguments, and so on. The arity of `func` can be specified
* if `func.length` is not sufficient.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to curry.
* @param {number} [arity=func.length] The arity of `func`.
* @returns {Function} Returns the new curried function.
* @example
*
* var curried = _.curry(function(a, b, c) {
* console.log(a + b + c);
* });
*
* curried(1)(2)(3);
* // => 6
*
* curried(1, 2)(3);
* // => 6
*
* curried(1, 2, 3);
* // => 6
*/
function curry(func, arity) {
arity = typeof arity == 'number' ? arity : (+arity || func.length);
return createWrapper(func, 4, null, null, null, arity);
}
module.exports = curry;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isFunction = require('../objects/isFunction'),
isObject = require('../objects/isObject'),
now = require('../utilities/now');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMax = Math.max;
/**
* Creates a function that will delay the execution of `func` until after
* `wait` milliseconds have elapsed since the last time it was invoked.
* Provide an options object to indicate that `func` should be invoked on
* the leading and/or trailing edge of the `wait` timeout. Subsequent calls
* to the debounced function will return the result of the last `func` call.
*
* Note: If `leading` and `trailing` options are `true` `func` will be called
* on the trailing edge of the timeout only if the the debounced function is
* invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to debounce.
* @param {number} wait The number of milliseconds to delay.
* @param {Object} [options] The options object.
* @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
* @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
* @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
* // avoid costly calculations while the window size is in flux
* var lazyLayout = _.debounce(calculateLayout, 150);
* jQuery(window).on('resize', lazyLayout);
*
* // execute `sendMail` when the click event is fired, debouncing subsequent calls
* jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false
* });
*
* // ensure `batchLog` is executed once after 1 second of debounced calls
* var source = new EventSource('/stream');
* source.addEventListener('message', _.debounce(batchLog, 250, {
* 'maxWait': 1000
* }, false);
*/
function debounce(func, wait, options) {
var args,
maxTimeoutId,
result,
stamp,
thisArg,
timeoutId,
trailingCall,
lastCalled = 0,
maxWait = false,
trailing = true;
if (!isFunction(func)) {
throw new TypeError;
}
wait = nativeMax(0, wait) || 0;
if (options === true) {
var leading = true;
trailing = false;
} else if (isObject(options)) {
leading = options.leading;
maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
trailing = 'trailing' in options ? options.trailing : trailing;
}
var delayed = function() {
var remaining = wait - (now() - stamp);
if (remaining <= 0) {
if (maxTimeoutId) {
clearTimeout(maxTimeoutId);
}
var isCalled = trailingCall;
maxTimeoutId = timeoutId = trailingCall = undefined;
if (isCalled) {
lastCalled = now();
result = func.apply(thisArg, args);
if (!timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
}
} else {
timeoutId = setTimeout(delayed, remaining);
}
};
var maxDelayed = function() {
if (timeoutId) {
clearTimeout(timeoutId);
}
maxTimeoutId = timeoutId = trailingCall = undefined;
if (trailing || (maxWait !== wait)) {
lastCalled = now();
result = func.apply(thisArg, args);
if (!timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
}
};
return function() {
args = arguments;
stamp = now();
thisArg = this;
trailingCall = trailing && (timeoutId || !leading);
if (maxWait === false) {
var leadingCall = leading && !timeoutId;
} else {
if (!maxTimeoutId && !leading) {
lastCalled = stamp;
}
var remaining = maxWait - (stamp - lastCalled),
isCalled = remaining <= 0;
if (isCalled) {
if (maxTimeoutId) {
maxTimeoutId = clearTimeout(maxTimeoutId);
}
lastCalled = stamp;
result = func.apply(thisArg, args);
}
else if (!maxTimeoutId) {
maxTimeoutId = setTimeout(maxDelayed, remaining);
}
}
if (isCalled && timeoutId) {
timeoutId = clearTimeout(timeoutId);
}
else if (!timeoutId && wait !== maxWait) {
timeoutId = setTimeout(delayed, wait);
}
if (leadingCall) {
isCalled = true;
result = func.apply(thisArg, args);
}
if (isCalled && !timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
return result;
};
}
module.exports = debounce;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isFunction = require('../objects/isFunction'),
slice = require('../internals/slice');
/**
* Defers executing the `func` function until the current call stack has cleared.
* Additional arguments will be provided to `func` when it is invoked.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to defer.
* @param {...*} [arg] Arguments to invoke the function with.
* @returns {number} Returns the timer id.
* @example
*
* _.defer(function(text) { console.log(text); }, 'deferred');
* // logs 'deferred' after one or more milliseconds
*/
function defer(func) {
if (!isFunction(func)) {
throw new TypeError;
}
var args = slice(arguments, 1);
return setTimeout(function() { func.apply(undefined, args); }, 1);
}
module.exports = defer;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isFunction = require('../objects/isFunction'),
slice = require('../internals/slice');
/**
* Executes the `func` function after `wait` milliseconds. Additional arguments
* will be provided to `func` when it is invoked.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to delay.
* @param {number} wait The number of milliseconds to delay execution.
* @param {...*} [arg] Arguments to invoke the function with.
* @returns {number} Returns the timer id.
* @example
*
* _.delay(function(text) { console.log(text); }, 1000, 'later');
* // => logs 'later' after one second
*/
function delay(func, wait) {
if (!isFunction(func)) {
throw new TypeError;
}
var args = slice(arguments, 2);
return setTimeout(function() { func.apply(undefined, args); }, wait);
}
module.exports = delay;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isFunction = require('../objects/isFunction'),
keyPrefix = require('../internals/keyPrefix');
/** Used for native method references */
var objectProto = Object.prototype;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Creates a function that memoizes the result of `func`. If `resolver` is
* provided it will be used to determine the cache key for storing the result
* based on the arguments provided to the memoized function. By default, the
* first argument provided to the memoized function is used as the cache key.
* The `func` is executed with the `this` binding of the memoized function.
* The result cache is exposed as the `cache` property on the memoized function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to have its output memoized.
* @param {Function} [resolver] A function used to resolve the cache key.
* @returns {Function} Returns the new memoizing function.
* @example
*
* var fibonacci = _.memoize(function(n) {
* return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
* });
*
* fibonacci(9)
* // => 34
*
* var data = {
* 'fred': { 'name': 'fred', 'age': 40 },
* 'pebbles': { 'name': 'pebbles', 'age': 1 }
* };
*
* // modifying the result cache
* var get = _.memoize(function(name) { return data[name]; }, _.identity);
* get('pebbles');
* // => { 'name': 'pebbles', 'age': 1 }
*
* get.cache.pebbles.name = 'penelope';
* get('pebbles');
* // => { 'name': 'penelope', 'age': 1 }
*/
function memoize(func, resolver) {
if (!isFunction(func)) {
throw new TypeError;
}
var memoized = function() {
var cache = memoized.cache,
key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
return hasOwnProperty.call(cache, key)
? cache[key]
: (cache[key] = func.apply(this, arguments));
}
memoized.cache = {};
return memoized;
}
module.exports = memoize;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isFunction = require('../objects/isFunction');
/**
* Creates a function that is restricted to execute `func` once. Repeat calls to
* the function will return the value of the first call. The `func` is executed
* with the `this` binding of the created function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var initialize = _.once(createApplication);
* initialize();
* initialize();
* // `initialize` executes `createApplication` once
*/
function once(func) {
var ran,
result;
if (!isFunction(func)) {
throw new TypeError;
}
return function() {
if (ran) {
return result;
}
ran = true;
result = func.apply(this, arguments);
// clear the `func` variable so the function may be garbage collected
func = null;
return result;
};
}
module.exports = once;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createWrapper = require('../internals/createWrapper'),
slice = require('../internals/slice');
/**
* Creates a function that, when called, invokes `func` with any additional
* `partial` arguments prepended to those provided to the new function. This
* method is similar to `_.bind` except it does **not** alter the `this` binding.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to partially apply arguments to.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* var greet = function(greeting, name) { return greeting + ' ' + name; };
* var hi = _.partial(greet, 'hi');
* hi('fred');
* // => 'hi fred'
*/
function partial(func) {
return createWrapper(func, 16, slice(arguments, 1));
}
module.exports = partial;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createWrapper = require('../internals/createWrapper'),
slice = require('../internals/slice');
/**
* This method is like `_.partial` except that `partial` arguments are
* appended to those provided to the new function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to partially apply arguments to.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* var defaultsDeep = _.partialRight(_.merge, _.defaults);
*
* var options = {
* 'variable': 'data',
* 'imports': { 'jq': $ }
* };
*
* defaultsDeep(options, _.templateSettings);
*
* options.variable
* // => 'data'
*
* options.imports
* // => { '_': _, 'jq': $ }
*/
function partialRight(func) {
return createWrapper(func, 32, null, slice(arguments, 1));
}
module.exports = partialRight;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var debounce = require('./debounce'),
isFunction = require('../objects/isFunction'),
isObject = require('../objects/isObject');
/** Used as an internal `_.debounce` options object */
var debounceOptions = {
'leading': false,
'maxWait': 0,
'trailing': false
};
/**
* Creates a function that, when executed, will only call the `func` function
* at most once per every `wait` milliseconds. Provide an options object to
* indicate that `func` should be invoked on the leading and/or trailing edge
* of the `wait` timeout. Subsequent calls to the throttled function will
* return the result of the last `func` call.
*
* Note: If `leading` and `trailing` options are `true` `func` will be called
* on the trailing edge of the timeout only if the the throttled function is
* invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to throttle.
* @param {number} wait The number of milliseconds to throttle executions to.
* @param {Object} [options] The options object.
* @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
* @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function.
* @example
*
* // avoid excessively updating the position while scrolling
* var throttled = _.throttle(updatePosition, 100);
* jQuery(window).on('scroll', throttled);
*
* // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
* jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
* 'trailing': false
* }));
*/
function throttle(func, wait, options) {
var leading = true,
trailing = true;
if (!isFunction(func)) {
throw new TypeError;
}
if (options === false) {
leading = false;
} else if (isObject(options)) {
leading = 'leading' in options ? options.leading : leading;
trailing = 'trailing' in options ? options.trailing : trailing;
}
debounceOptions.leading = leading;
debounceOptions.maxWait = wait;
debounceOptions.trailing = trailing;
return debounce(func, wait, debounceOptions);
}
module.exports = throttle;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createWrapper = require('../internals/createWrapper');
/**
* Creates a function that provides `value` to the wrapper function as its
* first argument. Additional arguments provided to the function are appended
* to those provided to the wrapper function. The wrapper is executed with
* the `this` binding of the created function.
*
* @static
* @memberOf _
* @category Functions
* @param {*} value The value to wrap.
* @param {Function} wrapper The wrapper function.
* @returns {Function} Returns the new function.
* @example
*
* var p = _.wrap(_.escape, function(func, text) {
* return '<p>' + func(text) + '</p>';
* });
*
* p('Fred, Wilma, & Pebbles');
* // => '<p>Fred, Wilma, & Pebbles</p>'
*/
function wrap(value, wrapper) {
return createWrapper(wrapper, 16, [value]);
}
module.exports = wrap;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| arrayPool.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| baseBind.js | 37.5% | (6 / 16) | 0% | (0 / 10) | 0% | (0 / 2) | 37.5% | (6 / 16) | |
| baseClone.js | 31.75% | (20 / 63) | 0% | (0 / 37) | 0% | (0 / 2) | 31.75% | (20 / 63) | |
| baseCreate.js | 42.86% | (6 / 14) | 30% | (3 / 10) | 0% | (0 / 4) | 42.86% | (6 / 14) | |
| baseCreateCallback.js | 17.65% | (6 / 34) | 0% | (0 / 27) | 0% | (0 / 5) | 17.65% | (6 / 34) | |
| baseCreateWrapper.js | 20.69% | (6 / 29) | 0% | (0 / 26) | 0% | (0 / 2) | 20.69% | (6 / 29) | |
| baseDifference.js | 17.65% | (3 / 17) | 0% | (0 / 10) | 0% | (0 / 1) | 17.65% | (3 / 17) | |
| baseFlatten.js | 18.75% | (3 / 16) | 0% | (0 / 15) | 0% | (0 / 1) | 18.75% | (3 / 16) | |
| baseIndexOf.js | 28.57% | (2 / 7) | 0% | (0 / 6) | 0% | (0 / 1) | 28.57% | (2 / 7) | |
| baseIsEqual.js | 9.09% | (7 / 77) | 0% | (0 / 88) | 0% | (0 / 3) | 9.09% | (7 / 77) | |
| baseMerge.js | 10% | (3 / 30) | 0% | (0 / 31) | 0% | (0 / 2) | 10% | (3 / 30) | |
| baseRandom.js | 80% | (4 / 5) | 100% | (0 / 0) | 0% | (0 / 1) | 80% | (4 / 5) | |
| baseUniq.js | 14.29% | (3 / 21) | 0% | (0 / 26) | 0% | (0 / 1) | 14.29% | (3 / 21) | |
| cacheIndexOf.js | 25% | (3 / 12) | 0% | (0 / 22) | 0% | (0 / 1) | 25% | (3 / 12) | |
| cachePush.js | 25% | (3 / 12) | 0% | (0 / 16) | 0% | (0 / 1) | 25% | (3 / 12) | |
| charAtCallback.js | 66.67% | (2 / 3) | 100% | (0 / 0) | 0% | (0 / 1) | 66.67% | (2 / 3) | |
| compareAscending.js | 18.18% | (2 / 11) | 0% | (0 / 10) | 0% | (0 / 1) | 18.18% | (2 / 11) | |
| createAggregator.js | 28.57% | (4 / 14) | 0% | (0 / 4) | 33.33% | (1 / 3) | 28.57% | (4 / 14) | |
| createCache.js | 20% | (3 / 15) | 0% | (0 / 8) | 0% | (0 / 1) | 20% | (3 / 15) | |
| createWrapper.js | 14.29% | (5 / 35) | 0% | (0 / 46) | 0% | (0 / 1) | 14.29% | (5 / 35) | |
| escapeHtmlChar.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| escapeStringChar.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| getArray.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| getObject.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| htmlEscapes.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| htmlUnescapes.js | 100% | (3 / 3) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (3 / 3) | |
| isNative.js | 100% | (6 / 6) | 100% | (2 / 2) | 100% | (1 / 1) | 100% | (6 / 6) | |
| keyPrefix.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| largeArraySize.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| lodashWrapper.js | 50% | (2 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 50% | (2 / 4) | |
| maxPoolSize.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| objectPool.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| objectTypes.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| reEscapedHtml.js | 100% | (3 / 3) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (3 / 3) | |
| reInterpolate.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| reUnescapedHtml.js | 100% | (3 / 3) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (3 / 3) | |
| releaseArray.js | 50% | (3 / 6) | 0% | (0 / 2) | 0% | (0 / 1) | 50% | (3 / 6) | |
| releaseObject.js | 33.33% | (3 / 9) | 0% | (0 / 4) | 0% | (0 / 1) | 33.33% | (3 / 9) | |
| setBindData.js | 80% | (8 / 10) | 83.33% | (5 / 6) | 50% | (1 / 2) | 80% | (8 / 10) | |
| shimIsPlainObject.js | 53.85% | (7 / 13) | 0% | (0 / 10) | 0% | (0 / 2) | 53.85% | (7 / 13) | |
| shimKeys.js | 35.71% | (5 / 14) | 0% | (0 / 6) | 0% | (0 / 1) | 41.67% | (5 / 12) | |
| slice.js | 22.22% | (2 / 9) | 0% | (0 / 10) | 0% | (0 / 1) | 22.22% | (2 / 9) | |
| unescapeHtmlChar.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 1 1 | /** * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/> * Build: `lodash modularize modern exports="node" -o ./modern/` * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE> * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <http://lodash.com/license> */ /** Used to pool arrays and objects used internally */ var arrayPool = []; module.exports = arrayPool; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreate = require('./baseCreate'),
isObject = require('../objects/isObject'),
setBindData = require('./setBindData'),
slice = require('./slice');
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Native method shortcuts */
var push = arrayRef.push;
/**
* The base implementation of `_.bind` that creates the bound function and
* sets its meta data.
*
* @private
* @param {Array} bindData The bind data array.
* @returns {Function} Returns the new bound function.
*/
function baseBind(bindData) {
var func = bindData[0],
partialArgs = bindData[2],
thisArg = bindData[4];
function bound() {
// `Function#bind` spec
// http://es5.github.io/#x15.3.4.5
if (partialArgs) {
// avoid `arguments` object deoptimizations by using `slice` instead
// of `Array.prototype.slice.call` and not assigning `arguments` to a
// variable as a ternary expression
var args = slice(partialArgs);
push.apply(args, arguments);
}
// mimic the constructor's `return` behavior
// http://es5.github.io/#x13.2.2
if (this instanceof bound) {
// ensure `new bound` is an instance of `func`
var thisBinding = baseCreate(func.prototype),
result = func.apply(thisBinding, args || arguments);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisArg, args || arguments);
}
setBindData(bound, bindData);
return bound;
}
module.exports = baseBind;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var assign = require('../objects/assign'),
forEach = require('../collections/forEach'),
forOwn = require('../objects/forOwn'),
getArray = require('./getArray'),
isArray = require('../objects/isArray'),
isObject = require('../objects/isObject'),
releaseArray = require('./releaseArray'),
slice = require('./slice');
/** Used to match regexp flags from their coerced string values */
var reFlags = /\w*$/;
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
arrayClass = '[object Array]',
boolClass = '[object Boolean]',
dateClass = '[object Date]',
funcClass = '[object Function]',
numberClass = '[object Number]',
objectClass = '[object Object]',
regexpClass = '[object RegExp]',
stringClass = '[object String]';
/** Used to identify object classifications that `_.clone` supports */
var cloneableClasses = {};
cloneableClasses[funcClass] = false;
cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
cloneableClasses[boolClass] = cloneableClasses[dateClass] =
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/** Used to lookup a built-in constructor by [[Class]] */
var ctorByClass = {};
ctorByClass[arrayClass] = Array;
ctorByClass[boolClass] = Boolean;
ctorByClass[dateClass] = Date;
ctorByClass[funcClass] = Function;
ctorByClass[objectClass] = Object;
ctorByClass[numberClass] = Number;
ctorByClass[regexpClass] = RegExp;
ctorByClass[stringClass] = String;
/**
* The base implementation of `_.clone` without argument juggling or support
* for `thisArg` binding.
*
* @private
* @param {*} value The value to clone.
* @param {boolean} [isDeep=false] Specify a deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {Array} [stackA=[]] Tracks traversed source objects.
* @param {Array} [stackB=[]] Associates clones with source counterparts.
* @returns {*} Returns the cloned value.
*/
function baseClone(value, isDeep, callback, stackA, stackB) {
if (callback) {
var result = callback(value);
if (typeof result != 'undefined') {
return result;
}
}
// inspect [[Class]]
var isObj = isObject(value);
if (isObj) {
var className = toString.call(value);
if (!cloneableClasses[className]) {
return value;
}
var ctor = ctorByClass[className];
switch (className) {
case boolClass:
case dateClass:
return new ctor(+value);
case numberClass:
case stringClass:
return new ctor(value);
case regexpClass:
result = ctor(value.source, reFlags.exec(value));
result.lastIndex = value.lastIndex;
return result;
}
} else {
return value;
}
var isArr = isArray(value);
if (isDeep) {
// check for circular references and return corresponding clone
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == value) {
return stackB[length];
}
}
result = isArr ? ctor(value.length) : {};
}
else {
result = isArr ? slice(value) : assign({}, value);
}
// add array properties assigned by `RegExp#exec`
if (isArr) {
if (hasOwnProperty.call(value, 'index')) {
result.index = value.index;
}
if (hasOwnProperty.call(value, 'input')) {
result.input = value.input;
}
}
// exit for shallow clone
if (!isDeep) {
return result;
}
// add the source value to the stack of traversed objects
// and associate it with its clone
stackA.push(value);
stackB.push(result);
// recursively populate clone (susceptible to call stack limits)
(isArr ? forEach : forOwn)(value, function(objValue, key) {
result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
});
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
module.exports = baseClone;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNative = require('./isNative'),
isObject = require('../objects/isObject'),
noop = require('../utilities/noop');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate;
/**
* The base implementation of `_.create` without support for assigning
* properties to the created object.
*
* @private
* @param {Object} prototype The object to inherit from.
* @returns {Object} Returns the new object.
*/
function baseCreate(prototype, properties) {
return isObject(prototype) ? nativeCreate(prototype) : {};
}
// fallback for browsers without `Object.create`
Iif (!nativeCreate) {
baseCreate = (function() {
function Object() {}
return function(prototype) {
if (isObject(prototype)) {
Object.prototype = prototype;
var result = new Object;
Object.prototype = null;
}
return result || global.Object();
};
}());
}
module.exports = baseCreate;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var bind = require('../functions/bind'),
identity = require('../utilities/identity'),
setBindData = require('./setBindData'),
support = require('../support');
/** Used to detected named functions */
var reFuncName = /^\s*function[ \n\r\t]+\w/;
/** Used to detect functions containing a `this` reference */
var reThis = /\bthis\b/;
/** Native method shortcuts */
var fnToString = Function.prototype.toString;
/**
* The base implementation of `_.createCallback` without support for creating
* "_.pluck" or "_.where" style callbacks.
*
* @private
* @param {*} [func=identity] The value to convert to a callback.
* @param {*} [thisArg] The `this` binding of the created callback.
* @param {number} [argCount] The number of arguments the callback accepts.
* @returns {Function} Returns a callback function.
*/
function baseCreateCallback(func, thisArg, argCount) {
if (typeof func != 'function') {
return identity;
}
// exit early for no `thisArg` or already bound by `Function#bind`
if (typeof thisArg == 'undefined' || !('prototype' in func)) {
return func;
}
var bindData = func.__bindData__;
if (typeof bindData == 'undefined') {
if (support.funcNames) {
bindData = !func.name;
}
bindData = bindData || !support.funcDecomp;
if (!bindData) {
var source = fnToString.call(func);
if (!support.funcNames) {
bindData = !reFuncName.test(source);
}
if (!bindData) {
// checks if `func` references the `this` keyword and stores the result
bindData = reThis.test(source);
setBindData(func, bindData);
}
}
}
// exit early if there are no `this` references or `func` is bound
if (bindData === false || (bindData !== true && bindData[1] & 1)) {
return func;
}
switch (argCount) {
case 1: return function(value) {
return func.call(thisArg, value);
};
case 2: return function(a, b) {
return func.call(thisArg, a, b);
};
case 3: return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
}
return bind(func, thisArg);
}
module.exports = baseCreateCallback;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreate = require('./baseCreate'),
isObject = require('../objects/isObject'),
setBindData = require('./setBindData'),
slice = require('./slice');
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Native method shortcuts */
var push = arrayRef.push;
/**
* The base implementation of `createWrapper` that creates the wrapper and
* sets its meta data.
*
* @private
* @param {Array} bindData The bind data array.
* @returns {Function} Returns the new function.
*/
function baseCreateWrapper(bindData) {
var func = bindData[0],
bitmask = bindData[1],
partialArgs = bindData[2],
partialRightArgs = bindData[3],
thisArg = bindData[4],
arity = bindData[5];
var isBind = bitmask & 1,
isBindKey = bitmask & 2,
isCurry = bitmask & 4,
isCurryBound = bitmask & 8,
key = func;
function bound() {
var thisBinding = isBind ? thisArg : this;
if (partialArgs) {
var args = slice(partialArgs);
push.apply(args, arguments);
}
if (partialRightArgs || isCurry) {
args || (args = slice(arguments));
if (partialRightArgs) {
push.apply(args, partialRightArgs);
}
if (isCurry && args.length < arity) {
bitmask |= 16 & ~32;
return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
}
}
args || (args = arguments);
if (isBindKey) {
func = thisBinding[key];
}
if (this instanceof bound) {
thisBinding = baseCreate(func.prototype);
var result = func.apply(thisBinding, args);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisBinding, args);
}
setBindData(bound, bindData);
return bound;
}
module.exports = baseCreateWrapper;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseIndexOf = require('./baseIndexOf'),
cacheIndexOf = require('./cacheIndexOf'),
createCache = require('./createCache'),
largeArraySize = require('./largeArraySize'),
releaseObject = require('./releaseObject');
/**
* The base implementation of `_.difference` that accepts a single array
* of values to exclude.
*
* @private
* @param {Array} array The array to process.
* @param {Array} [values] The array of values to exclude.
* @returns {Array} Returns a new array of filtered values.
*/
function baseDifference(array, values) {
var index = -1,
indexOf = baseIndexOf,
length = array ? array.length : 0,
isLarge = length >= largeArraySize,
result = [];
if (isLarge) {
var cache = createCache(values);
if (cache) {
indexOf = cacheIndexOf;
values = cache;
} else {
isLarge = false;
}
}
while (++index < length) {
var value = array[index];
if (indexOf(values, value) < 0) {
result.push(value);
}
}
if (isLarge) {
releaseObject(values);
}
return result;
}
module.exports = baseDifference;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isArguments = require('../objects/isArguments'),
isArray = require('../objects/isArray');
/**
* The base implementation of `_.flatten` without support for callback
* shorthands or `thisArg` binding.
*
* @private
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
* @param {number} [fromIndex=0] The index to start from.
* @returns {Array} Returns a new flattened array.
*/
function baseFlatten(array, isShallow, isStrict, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (value && typeof value == 'object' && typeof value.length == 'number'
&& (isArray(value) || isArguments(value))) {
// recursively flatten arrays (susceptible to call stack limits)
if (!isShallow) {
value = baseFlatten(value, isShallow, isStrict);
}
var valIndex = -1,
valLength = value.length,
resIndex = result.length;
result.length += valLength;
while (++valIndex < valLength) {
result[resIndex++] = value[valIndex];
}
} else if (!isStrict) {
result.push(value);
}
}
return result;
}
module.exports = baseFlatten;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* The base implementation of `_.indexOf` without support for binary searches
* or `fromIndex` constraints.
*
* @private
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @returns {number} Returns the index of the matched value or `-1`.
*/
function baseIndexOf(array, value, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array ? array.length : 0;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
module.exports = baseIndexOf;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | 1 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var forIn = require('../objects/forIn'),
getArray = require('./getArray'),
isFunction = require('../objects/isFunction'),
objectTypes = require('./objectTypes'),
releaseArray = require('./releaseArray');
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
arrayClass = '[object Array]',
boolClass = '[object Boolean]',
dateClass = '[object Date]',
numberClass = '[object Number]',
objectClass = '[object Object]',
regexpClass = '[object RegExp]',
stringClass = '[object String]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* The base implementation of `_.isEqual`, without support for `thisArg` binding,
* that allows partial "_.where" style comparisons.
*
* @private
* @param {*} a The value to compare.
* @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
* @param {Array} [stackA=[]] Tracks traversed `a` objects.
* @param {Array} [stackB=[]] Tracks traversed `b` objects.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/
function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
// used to indicate that when comparing objects, `a` has at least the properties of `b`
if (callback) {
var result = callback(a, b);
if (typeof result != 'undefined') {
return !!result;
}
}
// exit early for identical values
if (a === b) {
// treat `+0` vs. `-0` as not equal
return a !== 0 || (1 / a == 1 / b);
}
var type = typeof a,
otherType = typeof b;
// exit early for unlike primitive values
if (a === a &&
!(a && objectTypes[type]) &&
!(b && objectTypes[otherType])) {
return false;
}
// exit early for `null` and `undefined` avoiding ES3's Function#call behavior
// http://es5.github.io/#x15.3.4.4
if (a == null || b == null) {
return a === b;
}
// compare [[Class]] names
var className = toString.call(a),
otherClass = toString.call(b);
if (className == argsClass) {
className = objectClass;
}
if (otherClass == argsClass) {
otherClass = objectClass;
}
if (className != otherClass) {
return false;
}
switch (className) {
case boolClass:
case dateClass:
// coerce dates and booleans to numbers, dates to milliseconds and booleans
// to `1` or `0` treating invalid dates coerced to `NaN` as not equal
return +a == +b;
case numberClass:
// treat `NaN` vs. `NaN` as equal
return (a != +a)
? b != +b
// but treat `+0` vs. `-0` as not equal
: (a == 0 ? (1 / a == 1 / b) : a == +b);
case regexpClass:
case stringClass:
// coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
// treat string primitives and their corresponding object instances as equal
return a == String(b);
}
var isArr = className == arrayClass;
if (!isArr) {
// unwrap any `lodash` wrapped values
var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
bWrapped = hasOwnProperty.call(b, '__wrapped__');
if (aWrapped || bWrapped) {
return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
}
// exit for functions and DOM nodes
if (className != objectClass) {
return false;
}
// in older versions of Opera, `arguments` objects have `Array` constructors
var ctorA = a.constructor,
ctorB = b.constructor;
// non `Object` object instances with different constructors are not equal
if (ctorA != ctorB &&
!(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
('constructor' in a && 'constructor' in b)
) {
return false;
}
}
// assume cyclic structures are equal
// the algorithm for detecting cyclic structures is adapted from ES 5.1
// section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == a) {
return stackB[length] == b;
}
}
var size = 0;
result = true;
// add `a` and `b` to the stack of traversed objects
stackA.push(a);
stackB.push(b);
// recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) {
// compare lengths to determine if a deep comparison is necessary
length = a.length;
size = b.length;
result = size == length;
if (result || isWhere) {
// deep compare the contents, ignoring non-numeric properties
while (size--) {
var index = length,
value = b[size];
if (isWhere) {
while (index--) {
if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
break;
}
}
} else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
break;
}
}
}
}
else {
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
// which, in this case, is more costly
forIn(b, function(value, key, b) {
if (hasOwnProperty.call(b, key)) {
// count the number of properties.
size++;
// deep compare each property value.
return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
}
});
if (result && !isWhere) {
// ensure both objects have the same number of properties
forIn(a, function(value, key, a) {
if (hasOwnProperty.call(a, key)) {
// `size` will be `-1` if `a` has more properties than `b`
return (result = --size > -1);
}
});
}
}
stackA.pop();
stackB.pop();
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
module.exports = baseIsEqual;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var forEach = require('../collections/forEach'),
forOwn = require('../objects/forOwn'),
isArray = require('../objects/isArray'),
isPlainObject = require('../objects/isPlainObject');
/**
* The base implementation of `_.merge` without argument juggling or support
* for `thisArg` binding.
*
* @private
* @param {Object} object The destination object.
* @param {Object} source The source object.
* @param {Function} [callback] The function to customize merging properties.
* @param {Array} [stackA=[]] Tracks traversed source objects.
* @param {Array} [stackB=[]] Associates values with source counterparts.
*/
function baseMerge(object, source, callback, stackA, stackB) {
(isArray(source) ? forEach : forOwn)(source, function(source, key) {
var found,
isArr,
result = source,
value = object[key];
if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
// avoid merging previously merged cyclic sources
var stackLength = stackA.length;
while (stackLength--) {
if ((found = stackA[stackLength] == source)) {
value = stackB[stackLength];
break;
}
}
if (!found) {
var isShallow;
if (callback) {
result = callback(value, source);
if ((isShallow = typeof result != 'undefined')) {
value = result;
}
}
if (!isShallow) {
value = isArr
? (isArray(value) ? value : [])
: (isPlainObject(value) ? value : {});
}
// add `source` and associated `value` to the stack of traversed objects
stackA.push(source);
stackB.push(value);
// recursively merge objects and arrays (susceptible to call stack limits)
if (!isShallow) {
baseMerge(value, source, callback, stackA, stackB);
}
}
}
else {
if (callback) {
result = callback(value, source);
if (typeof result == 'undefined') {
result = source;
}
}
if (typeof result != 'undefined') {
value = result;
}
}
object[key] = value;
});
}
module.exports = baseMerge;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Native method shortcuts */
var floor = Math.floor;
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeRandom = Math.random;
/**
* The base implementation of `_.random` without argument juggling or support
* for returning floating-point numbers.
*
* @private
* @param {number} min The minimum possible value.
* @param {number} max The maximum possible value.
* @returns {number} Returns a random number.
*/
function baseRandom(min, max) {
return min + floor(nativeRandom() * (max - min + 1));
}
module.exports = baseRandom;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseIndexOf = require('./baseIndexOf'),
cacheIndexOf = require('./cacheIndexOf'),
createCache = require('./createCache'),
getArray = require('./getArray'),
largeArraySize = require('./largeArraySize'),
releaseArray = require('./releaseArray'),
releaseObject = require('./releaseObject');
/**
* The base implementation of `_.uniq` without support for callback shorthands
* or `thisArg` binding.
*
* @private
* @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
* @param {Function} [callback] The function called per iteration.
* @returns {Array} Returns a duplicate-value-free array.
*/
function baseUniq(array, isSorted, callback) {
var index = -1,
indexOf = baseIndexOf,
length = array ? array.length : 0,
result = [];
var isLarge = !isSorted && length >= largeArraySize,
seen = (callback || isLarge) ? getArray() : result;
if (isLarge) {
var cache = createCache(seen);
indexOf = cacheIndexOf;
seen = cache;
}
while (++index < length) {
var value = array[index],
computed = callback ? callback(value, index, array) : value;
if (isSorted
? !index || seen[seen.length - 1] !== computed
: indexOf(seen, computed) < 0
) {
if (callback || isLarge) {
seen.push(computed);
}
result.push(value);
}
}
if (isLarge) {
releaseArray(seen.array);
releaseObject(seen);
} else if (callback) {
releaseArray(seen);
}
return result;
}
module.exports = baseUniq;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseIndexOf = require('./baseIndexOf'),
keyPrefix = require('./keyPrefix');
/**
* An implementation of `_.contains` for cache objects that mimics the return
* signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
*
* @private
* @param {Object} cache The cache object to inspect.
* @param {*} value The value to search for.
* @returns {number} Returns `0` if `value` is found, else `-1`.
*/
function cacheIndexOf(cache, value) {
var type = typeof value;
cache = cache.cache;
if (type == 'boolean' || value == null) {
return cache[value] ? 0 : -1;
}
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value;
cache = (cache = cache[type]) && cache[key];
return type == 'object'
? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
: (cache ? 0 : -1);
}
module.exports = cacheIndexOf;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var keyPrefix = require('./keyPrefix');
/**
* Adds a given value to the corresponding cache object.
*
* @private
* @param {*} value The value to add to the cache.
*/
function cachePush(value) {
var cache = this.cache,
type = typeof value;
if (type == 'boolean' || value == null) {
cache[value] = true;
} else {
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value,
typeCache = cache[type] || (cache[type] = {});
if (type == 'object') {
(typeCache[key] || (typeCache[key] = [])).push(value);
} else {
typeCache[key] = true;
}
}
}
module.exports = cachePush;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Used by `_.max` and `_.min` as the default callback when a given
* collection is a string value.
*
* @private
* @param {string} value The character to inspect.
* @returns {number} Returns the code unit of given character.
*/
function charAtCallback(value) {
return value.charCodeAt(0);
}
module.exports = charAtCallback;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Used by `sortBy` to compare transformed `collection` elements, stable sorting
* them in ascending order.
*
* @private
* @param {Object} a The object to compare to `b`.
* @param {Object} b The object to compare to `a`.
* @returns {number} Returns the sort order indicator of `1` or `-1`.
*/
function compareAscending(a, b) {
var ac = a.criteria,
bc = b.criteria,
index = -1,
length = ac.length;
while (++index < length) {
var value = ac[index],
other = bc[index];
if (value !== other) {
if (value > other || typeof value == 'undefined') {
return 1;
}
if (value < other || typeof other == 'undefined') {
return -1;
}
}
}
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
// that causes it, under certain circumstances, to return the same value for
// `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
//
// This also ensures a stable sort in V8 and other engines.
// See http://code.google.com/p/v8/issues/detail?id=90
return a.index - b.index;
}
module.exports = compareAscending;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 1 1 3 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('../objects/forOwn'),
isArray = require('../objects/isArray');
/**
* Creates a function that aggregates a collection, creating an object composed
* of keys generated from the results of running each element of the collection
* through a callback. The given `setter` function sets the keys and values
* of the composed object.
*
* @private
* @param {Function} setter The setter function.
* @returns {Function} Returns the new aggregator function.
*/
function createAggregator(setter) {
return function(collection, callback, thisArg) {
var result = {};
callback = createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
setter(result, value, callback(value, index, collection), collection);
}
} else {
forOwn(collection, function(value, key, collection) {
setter(result, value, callback(value, key, collection), collection);
});
}
return result;
};
}
module.exports = createAggregator;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var cachePush = require('./cachePush'),
getObject = require('./getObject'),
releaseObject = require('./releaseObject');
/**
* Creates a cache object to optimize linear searches of large arrays.
*
* @private
* @param {Array} [array=[]] The array to search.
* @returns {null|Object} Returns the cache object or `null` if caching should not be used.
*/
function createCache(array) {
var index = -1,
length = array.length,
first = array[0],
mid = array[(length / 2) | 0],
last = array[length - 1];
if (first && typeof first == 'object' &&
mid && typeof mid == 'object' && last && typeof last == 'object') {
return false;
}
var cache = getObject();
cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
var result = getObject();
result.array = array;
result.cache = cache;
result.push = cachePush;
while (++index < length) {
result.push(array[index]);
}
return result;
}
module.exports = createCache;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseBind = require('./baseBind'),
baseCreateWrapper = require('./baseCreateWrapper'),
isFunction = require('../objects/isFunction'),
slice = require('./slice');
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Native method shortcuts */
var push = arrayRef.push,
unshift = arrayRef.unshift;
/**
* Creates a function that, when called, either curries or invokes `func`
* with an optional `this` binding and partially applied arguments.
*
* @private
* @param {Function|string} func The function or method name to reference.
* @param {number} bitmask The bitmask of method flags to compose.
* The bitmask may be composed of the following flags:
* 1 - `_.bind`
* 2 - `_.bindKey`
* 4 - `_.curry`
* 8 - `_.curry` (bound)
* 16 - `_.partial`
* 32 - `_.partialRight`
* @param {Array} [partialArgs] An array of arguments to prepend to those
* provided to the new function.
* @param {Array} [partialRightArgs] An array of arguments to append to those
* provided to the new function.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new function.
*/
function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
var isBind = bitmask & 1,
isBindKey = bitmask & 2,
isCurry = bitmask & 4,
isCurryBound = bitmask & 8,
isPartial = bitmask & 16,
isPartialRight = bitmask & 32;
if (!isBindKey && !isFunction(func)) {
throw new TypeError;
}
if (isPartial && !partialArgs.length) {
bitmask &= ~16;
isPartial = partialArgs = false;
}
if (isPartialRight && !partialRightArgs.length) {
bitmask &= ~32;
isPartialRight = partialRightArgs = false;
}
var bindData = func && func.__bindData__;
if (bindData && bindData !== true) {
// clone `bindData`
bindData = slice(bindData);
if (bindData[2]) {
bindData[2] = slice(bindData[2]);
}
if (bindData[3]) {
bindData[3] = slice(bindData[3]);
}
// set `thisBinding` is not previously bound
if (isBind && !(bindData[1] & 1)) {
bindData[4] = thisArg;
}
// set if previously bound but not currently (subsequent curried functions)
if (!isBind && bindData[1] & 1) {
bitmask |= 8;
}
// set curried arity if not yet set
if (isCurry && !(bindData[1] & 4)) {
bindData[5] = arity;
}
// append partial left arguments
if (isPartial) {
push.apply(bindData[2] || (bindData[2] = []), partialArgs);
}
// append partial right arguments
if (isPartialRight) {
unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
}
// merge flags
bindData[1] |= bitmask;
return createWrapper.apply(null, bindData);
}
// fast path for `_.bind`
var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
}
module.exports = createWrapper;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var htmlEscapes = require('./htmlEscapes');
/**
* Used by `escape` to convert characters to HTML entities.
*
* @private
* @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeHtmlChar(match) {
return htmlEscapes[match];
}
module.exports = escapeHtmlChar;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Used to escape characters for inclusion in compiled string literals */
var stringEscapes = {
'\\': '\\',
"'": "'",
'\n': 'n',
'\r': 'r',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
/**
* Used by `template` to escape characters for inclusion in compiled
* string literals.
*
* @private
* @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeStringChar(match) {
return '\\' + stringEscapes[match];
}
module.exports = escapeStringChar;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var arrayPool = require('./arrayPool');
/**
* Gets an array from the array pool or creates a new one if the pool is empty.
*
* @private
* @returns {Array} The array from the pool.
*/
function getArray() {
return arrayPool.pop() || [];
}
module.exports = getArray;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var objectPool = require('./objectPool');
/**
* Gets an object from the object pool or creates a new one if the pool is empty.
*
* @private
* @returns {Object} The object from the pool.
*/
function getObject() {
return objectPool.pop() || {
'array': null,
'cache': null,
'criteria': null,
'false': false,
'index': 0,
'null': false,
'number': null,
'object': null,
'push': null,
'string': null,
'true': false,
'undefined': false,
'value': null
};
}
module.exports = getObject;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Used to convert characters to HTML entities:
*
* Though the `>` character is escaped for symmetry, characters like `>` and `/`
* don't require escaping in HTML and have no special meaning unless they're part
* of a tag or an unquoted attribute value.
* http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
*/
var htmlEscapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
module.exports = htmlEscapes;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var htmlEscapes = require('./htmlEscapes'),
invert = require('../objects/invert');
/** Used to convert HTML entities to characters */
var htmlUnescapes = invert(htmlEscapes);
module.exports = htmlUnescapes;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 1 1 1 1 7 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Used to detect if a method is native */
var reNative = RegExp('^' +
String(toString)
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
.replace(/toString| for [^\]]+/g, '.*?') + '$'
);
/**
* Checks if `value` is a native function.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
*/
function isNative(value) {
return typeof value == 'function' && reNative.test(value);
}
module.exports = isNative;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 1 1 | /** * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/> * Build: `lodash modularize modern exports="node" -o ./modern/` * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE> * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <http://lodash.com/license> */ /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */ var keyPrefix = +new Date + ''; module.exports = keyPrefix; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 1 1 | /** * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/> * Build: `lodash modularize modern exports="node" -o ./modern/` * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE> * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <http://lodash.com/license> */ /** Used as the size when optimizations are enabled for large arrays */ var largeArraySize = 75; module.exports = largeArraySize; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* A fast path for creating `lodash` wrapper objects.
*
* @private
* @param {*} value The value to wrap in a `lodash` instance.
* @param {boolean} chainAll A flag to enable chaining for all methods
* @returns {Object} Returns a `lodash` instance.
*/
function lodashWrapper(value, chainAll) {
this.__chain__ = !!chainAll;
this.__wrapped__ = value;
}
module.exports = lodashWrapper;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 1 1 | /** * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/> * Build: `lodash modularize modern exports="node" -o ./modern/` * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE> * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <http://lodash.com/license> */ /** Used as the max size of the `arrayPool` and `objectPool` */ var maxPoolSize = 40; module.exports = maxPoolSize; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 1 1 | /** * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/> * Build: `lodash modularize modern exports="node" -o ./modern/` * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE> * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <http://lodash.com/license> */ /** Used to pool arrays and objects used internally */ var objectPool = []; module.exports = objectPool; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Used to determine if values are of the language type Object */
var objectTypes = {
'boolean': false,
'function': true,
'object': true,
'number': false,
'string': false,
'undefined': false
};
module.exports = objectTypes;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var htmlUnescapes = require('./htmlUnescapes'),
keys = require('../objects/keys');
/** Used to match HTML entities and HTML characters */
var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g');
module.exports = reEscapedHtml;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 1 1 | /** * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/> * Build: `lodash modularize modern exports="node" -o ./modern/` * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/> * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE> * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors * Available under MIT license <http://lodash.com/license> */ /** Used to match "interpolate" template delimiters */ var reInterpolate = /<%=([\s\S]+?)%>/g; module.exports = reInterpolate; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var htmlEscapes = require('./htmlEscapes'),
keys = require('../objects/keys');
/** Used to match HTML entities and HTML characters */
var reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
module.exports = reUnescapedHtml;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var arrayPool = require('./arrayPool'),
maxPoolSize = require('./maxPoolSize');
/**
* Releases the given array back to the array pool.
*
* @private
* @param {Array} [array] The array to release.
*/
function releaseArray(array) {
array.length = 0;
if (arrayPool.length < maxPoolSize) {
arrayPool.push(array);
}
}
module.exports = releaseArray;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var maxPoolSize = require('./maxPoolSize'),
objectPool = require('./objectPool');
/**
* Releases the given object back to the object pool.
*
* @private
* @param {Object} [object] The object to release.
*/
function releaseObject(object) {
var cache = object.cache;
if (cache) {
releaseObject(cache);
}
object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
if (objectPool.length < maxPoolSize) {
objectPool.push(object);
}
}
module.exports = releaseObject;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 1 1 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNative = require('./isNative'),
noop = require('../utilities/noop');
/** Used as the property descriptor for `__bindData__` */
var descriptor = {
'configurable': false,
'enumerable': false,
'value': null,
'writable': false
};
/** Used to set meta data on functions */
var defineProperty = (function() {
// IE 8 only accepts DOM elements
try {
var o = {},
func = isNative(func = Object.defineProperty) && func,
result = func(o, o, o) && func;
} catch(e) { }
return result;
}());
/**
* Sets `this` binding data on a given function.
*
* @private
* @param {Function} func The function to set data on.
* @param {Array} value The data array to set.
*/
var setBindData = !defineProperty ? noop : function(func, value) {
descriptor.value = value;
defineProperty(func, '__bindData__', descriptor);
};
module.exports = setBindData;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 1 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var forIn = require('../objects/forIn'),
isFunction = require('../objects/isFunction');
/** `Object#toString` result shortcuts */
var objectClass = '[object Object]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* A fallback implementation of `isPlainObject` which checks if a given value
* is an object created by the `Object` constructor, assuming objects created
* by the `Object` constructor have no inherited enumerable properties and that
* there are no `Object.prototype` extensions.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
*/
function shimIsPlainObject(value) {
var ctor,
result;
// avoid non Object objects, `arguments` objects, and DOM elements
if (!(value && toString.call(value) == objectClass) ||
(ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
return false;
}
// In most environments an object's own properties are iterated before
// its inherited properties. If the last iterated property is an object's
// own property then there are no inherited enumerable properties.
forIn(value, function(value, key) {
result = key;
});
return typeof result == 'undefined' || hasOwnProperty.call(value, result);
}
module.exports = shimIsPlainObject;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var objectTypes = require('./objectTypes');
/** Used for native method references */
var objectProto = Object.prototype;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* A fallback implementation of `Object.keys` which produces an array of the
* given object's own enumerable property names.
*
* @private
* @type Function
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names.
*/
var shimKeys = function(object) {
var index, iterable = object, result = [];
if (!iterable) return result;
if (!(objectTypes[typeof object])) return result;
for (index in iterable) {
if (hasOwnProperty.call(iterable, index)) {
result.push(index);
}
}
return result
};
module.exports = shimKeys;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Slices the `collection` from the `start` index up to, but not including,
* the `end` index.
*
* Note: This function is used instead of `Array#slice` to support node lists
* in IE < 9 and to ensure dense arrays are returned.
*
* @private
* @param {Array|Object|string} collection The collection to slice.
* @param {number} start The start index.
* @param {number} end The end index.
* @returns {Array} Returns the new array.
*/
function slice(array, start, end) {
start || (start = 0);
if (typeof end == 'undefined') {
end = array ? array.length : 0;
}
var index = -1,
length = end - start || 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = array[start + index];
}
return result;
}
module.exports = slice;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var htmlUnescapes = require('./htmlUnescapes');
/**
* Used by `unescape` to convert HTML entities to characters.
*
* @private
* @param {string} match The matched character to unescape.
* @returns {string} Returns the unescaped character.
*/
function unescapeHtmlChar(match) {
return htmlUnescapes[match];
}
module.exports = unescapeHtmlChar;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| assign.js | 15.79% | (3 / 19) | 0% | (0 / 22) | 0% | (0 / 1) | 16.67% | (3 / 18) | |
| clone.js | 37.5% | (3 / 8) | 0% | (0 / 6) | 0% | (0 / 1) | 37.5% | (3 / 8) | |
| cloneDeep.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| create.js | 60% | (3 / 5) | 0% | (0 / 2) | 0% | (0 / 1) | 60% | (3 / 5) | |
| defaults.js | 18.75% | (3 / 16) | 0% | (0 / 14) | 0% | (0 / 1) | 21.43% | (3 / 14) | |
| findKey.js | 30% | (3 / 10) | 0% | (0 / 2) | 0% | (0 / 2) | 30% | (3 / 10) | |
| findLastKey.js | 30% | (3 / 10) | 0% | (0 / 2) | 0% | (0 / 2) | 30% | (3 / 10) | |
| forIn.js | 76.92% | (10 / 13) | 60% | (6 / 10) | 100% | (1 / 1) | 100% | (10 / 10) | |
| forInRight.js | 25% | (3 / 12) | 0% | (0 / 2) | 0% | (0 / 2) | 25% | (3 / 12) | |
| forOwn.js | 80% | (12 / 15) | 64.29% | (9 / 14) | 100% | (1 / 1) | 100% | (12 / 12) | |
| forOwnRight.js | 30% | (3 / 10) | 0% | (0 / 2) | 0% | (0 / 1) | 30% | (3 / 10) | |
| functions.js | 100% | (8 / 8) | 50% | (1 / 2) | 100% | (2 / 2) | 100% | (8 / 8) | |
| has.js | 80% | (4 / 5) | 0% | (0 / 2) | 0% | (0 / 1) | 80% | (4 / 5) | |
| invert.js | 100% | (8 / 8) | 100% | (0 / 0) | 100% | (1 / 1) | 100% | (8 / 8) | |
| isArguments.js | 83.33% | (5 / 6) | 0% | (0 / 5) | 0% | (0 / 1) | 83.33% | (5 / 6) | |
| isArray.js | 87.5% | (7 / 8) | 33.33% | (3 / 9) | 0% | (0 / 1) | 87.5% | (7 / 8) | |
| isBoolean.js | 83.33% | (5 / 6) | 0% | (0 / 6) | 0% | (0 / 1) | 83.33% | (5 / 6) | |
| isDate.js | 83.33% | (5 / 6) | 0% | (0 / 4) | 0% | (0 / 1) | 83.33% | (5 / 6) | |
| isElement.js | 66.67% | (2 / 3) | 0% | (0 / 3) | 0% | (0 / 1) | 66.67% | (2 / 3) | |
| isEmpty.js | 40% | (6 / 15) | 0% | (0 / 10) | 0% | (0 / 2) | 40% | (6 / 15) | |
| isEqual.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| isFinite.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| isFunction.js | 100% | (3 / 3) | 100% | (0 / 0) | 100% | (1 / 1) | 100% | (3 / 3) | |
| isNaN.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| isNull.js | 66.67% | (2 / 3) | 100% | (0 / 0) | 0% | (0 / 1) | 66.67% | (2 / 3) | |
| isNumber.js | 83.33% | (5 / 6) | 0% | (0 / 5) | 0% | (0 / 1) | 83.33% | (5 / 6) | |
| isObject.js | 100% | (4 / 4) | 100% | (2 / 2) | 100% | (1 / 1) | 100% | (4 / 4) | |
| isPlainObject.js | 63.64% | (7 / 11) | 20% | (3 / 15) | 0% | (0 / 1) | 63.64% | (7 / 11) | |
| isRegExp.js | 83.33% | (5 / 6) | 0% | (0 / 4) | 0% | (0 / 1) | 83.33% | (5 / 6) | |
| isString.js | 83.33% | (5 / 6) | 0% | (0 / 5) | 0% | (0 / 1) | 83.33% | (5 / 6) | |
| isUndefined.js | 66.67% | (2 / 3) | 100% | (0 / 0) | 0% | (0 / 1) | 66.67% | (2 / 3) | |
| keys.js | 85.71% | (6 / 7) | 66.67% | (4 / 6) | 100% | (1 / 1) | 85.71% | (6 / 7) | |
| mapValues.js | 37.5% | (3 / 8) | 100% | (0 / 0) | 0% | (0 / 2) | 37.5% | (3 / 8) | |
| merge.js | 16.67% | (3 / 18) | 0% | (0 / 12) | 0% | (0 / 1) | 16.67% | (3 / 18) | |
| omit.js | 16.67% | (3 / 18) | 0% | (0 / 4) | 0% | (0 / 3) | 16.67% | (3 / 18) | |
| pairs.js | 37.5% | (3 / 8) | 100% | (0 / 0) | 0% | (0 / 1) | 37.5% | (3 / 8) | |
| pick.js | 20% | (3 / 15) | 0% | (0 / 8) | 0% | (0 / 2) | 20% | (3 / 15) | |
| transform.js | 21.43% | (3 / 14) | 0% | (0 / 12) | 0% | (0 / 2) | 21.43% | (3 / 14) | |
| values.js | 42.86% | (3 / 7) | 100% | (0 / 0) | 0% | (0 / 1) | 42.86% | (3 / 7) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
keys = require('./keys'),
objectTypes = require('../internals/objectTypes');
/**
* Assigns own enumerable properties of source object(s) to the destination
* object. Subsequent sources will overwrite property assignments of previous
* sources. If a callback is provided it will be executed to produce the
* assigned values. The callback is bound to `thisArg` and invoked with two
* arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @type Function
* @alias extend
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param {Function} [callback] The function to customize assigning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
* @example
*
* _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
* // => { 'name': 'fred', 'employer': 'slate' }
*
* var defaults = _.partialRight(_.assign, function(a, b) {
* return typeof a == 'undefined' ? b : a;
* });
*
* var object = { 'name': 'barney' };
* defaults(object, { 'name': 'fred', 'employer': 'slate' });
* // => { 'name': 'barney', 'employer': 'slate' }
*/
var assign = function(object, source, guard) {
var index, iterable = object, result = iterable;
if (!iterable) return result;
var args = arguments,
argsIndex = 0,
argsLength = typeof guard == 'number' ? 2 : args.length;
if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
callback = args[--argsLength];
}
while (++argsIndex < argsLength) {
iterable = args[argsIndex];
if (iterable && objectTypes[typeof iterable]) {
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
}
}
}
return result
};
module.exports = assign;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseClone = require('../internals/baseClone'),
baseCreateCallback = require('../internals/baseCreateCallback');
/**
* Creates a clone of `value`. If `isDeep` is `true` nested objects will also
* be cloned, otherwise they will be assigned by reference. If a callback
* is provided it will be executed to produce the cloned values. If the
* callback returns `undefined` cloning will be handled by the method instead.
* The callback is bound to `thisArg` and invoked with one argument; (value).
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to clone.
* @param {boolean} [isDeep=false] Specify a deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the cloned value.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* var shallow = _.clone(characters);
* shallow[0] === characters[0];
* // => true
*
* var deep = _.clone(characters, true);
* deep[0] === characters[0];
* // => false
*
* _.mixin({
* 'clone': _.partialRight(_.clone, function(value) {
* return _.isElement(value) ? value.cloneNode(false) : undefined;
* })
* });
*
* var clone = _.clone(document.body);
* clone.childNodes.length;
* // => 0
*/
function clone(value, isDeep, callback, thisArg) {
// allows working with "Collections" methods without using their `index`
// and `collection` arguments for `isDeep` and `callback`
if (typeof isDeep != 'boolean' && isDeep != null) {
thisArg = callback;
callback = isDeep;
isDeep = false;
}
return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
}
module.exports = clone;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseClone = require('../internals/baseClone'),
baseCreateCallback = require('../internals/baseCreateCallback');
/**
* Creates a deep clone of `value`. If a callback is provided it will be
* executed to produce the cloned values. If the callback returns `undefined`
* cloning will be handled by the method instead. The callback is bound to
* `thisArg` and invoked with one argument; (value).
*
* Note: This method is loosely based on the structured clone algorithm. Functions
* and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
* objects created by constructors other than `Object` are cloned to plain `Object` objects.
* See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the deep cloned value.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* var deep = _.cloneDeep(characters);
* deep[0] === characters[0];
* // => false
*
* var view = {
* 'label': 'docs',
* 'node': element
* };
*
* var clone = _.cloneDeep(view, function(value) {
* return _.isElement(value) ? value.cloneNode(true) : undefined;
* });
*
* clone.node == view.node;
* // => false
*/
function cloneDeep(value, callback, thisArg) {
return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
}
module.exports = cloneDeep;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var assign = require('./assign'),
baseCreate = require('../internals/baseCreate');
/**
* Creates an object that inherits from the given `prototype` object. If a
* `properties` object is provided its own enumerable properties are assigned
* to the created object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} prototype The object to inherit from.
* @param {Object} [properties] The properties to assign to the object.
* @returns {Object} Returns the new object.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* function Circle() {
* Shape.call(this);
* }
*
* Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
*
* var circle = new Circle;
* circle instanceof Circle;
* // => true
*
* circle instanceof Shape;
* // => true
*/
function create(prototype, properties) {
var result = baseCreate(prototype);
return properties ? assign(result, properties) : result;
}
module.exports = create;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var keys = require('./keys'),
objectTypes = require('../internals/objectTypes');
/**
* Assigns own enumerable properties of source object(s) to the destination
* object for all destination properties that resolve to `undefined`. Once a
* property is set, additional defaults of the same property will be ignored.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param- {Object} [guard] Allows working with `_.reduce` without using its
* `key` and `object` arguments as sources.
* @returns {Object} Returns the destination object.
* @example
*
* var object = { 'name': 'barney' };
* _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
* // => { 'name': 'barney', 'employer': 'slate' }
*/
var defaults = function(object, source, guard) {
var index, iterable = object, result = iterable;
if (!iterable) return result;
var args = arguments,
argsIndex = 0,
argsLength = typeof guard == 'number' ? 2 : args.length;
while (++argsIndex < argsLength) {
iterable = args[argsIndex];
if (iterable && objectTypes[typeof iterable]) {
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
if (typeof result[index] == 'undefined') result[index] = iterable[index];
}
}
}
return result
};
module.exports = defaults;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('./forOwn');
/**
* This method is like `_.findIndex` except that it returns the key of the
* first element that passes the callback check, instead of the element itself.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
* @param {Function|Object|string} [callback=identity] The function called per
* iteration. If a property name or object is provided it will be used to
* create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example
*
* var characters = {
* 'barney': { 'age': 36, 'blocked': false },
* 'fred': { 'age': 40, 'blocked': true },
* 'pebbles': { 'age': 1, 'blocked': false }
* };
*
* _.findKey(characters, function(chr) {
* return chr.age < 40;
* });
* // => 'barney' (property order is not guaranteed across environments)
*
* // using "_.where" callback shorthand
* _.findKey(characters, { 'age': 1 });
* // => 'pebbles'
*
* // using "_.pluck" callback shorthand
* _.findKey(characters, 'blocked');
* // => 'fred'
*/
function findKey(object, callback, thisArg) {
var result;
callback = createCallback(callback, thisArg, 3);
forOwn(object, function(value, key, object) {
if (callback(value, key, object)) {
result = key;
return false;
}
});
return result;
}
module.exports = findKey;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwnRight = require('./forOwnRight');
/**
* This method is like `_.findKey` except that it iterates over elements
* of a `collection` in the opposite order.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
* @param {Function|Object|string} [callback=identity] The function called per
* iteration. If a property name or object is provided it will be used to
* create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example
*
* var characters = {
* 'barney': { 'age': 36, 'blocked': true },
* 'fred': { 'age': 40, 'blocked': false },
* 'pebbles': { 'age': 1, 'blocked': true }
* };
*
* _.findLastKey(characters, function(chr) {
* return chr.age < 40;
* });
* // => returns `pebbles`, assuming `_.findKey` returns `barney`
*
* // using "_.where" callback shorthand
* _.findLastKey(characters, { 'age': 40 });
* // => 'fred'
*
* // using "_.pluck" callback shorthand
* _.findLastKey(characters, 'blocked');
* // => 'pebbles'
*/
function findLastKey(object, callback, thisArg) {
var result;
callback = createCallback(callback, thisArg, 3);
forOwnRight(object, function(value, key, object) {
if (callback(value, key, object)) {
result = key;
return false;
}
});
return result;
}
module.exports = findLastKey;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 1 1 2 2 2 2 2 136 2 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
objectTypes = require('../internals/objectTypes');
/**
* Iterates over own and inherited enumerable properties of an object,
* executing the callback for each property. The callback is bound to `thisArg`
* and invoked with three arguments; (value, key, object). Callbacks may exit
* iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* Shape.prototype.move = function(x, y) {
* this.x += x;
* this.y += y;
* };
*
* _.forIn(new Shape, function(value, key) {
* console.log(key);
* });
* // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
*/
var forIn = function(collection, callback, thisArg) {
var index, iterable = collection, result = iterable;
Iif (!iterable) return result;
Iif (!objectTypes[typeof iterable]) return result;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
for (index in iterable) {
Iif (callback(iterable[index], index, collection) === false) return result;
}
return result
};
module.exports = forIn;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
forIn = require('./forIn');
/**
* This method is like `_.forIn` except that it iterates over elements
* of a `collection` in the opposite order.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* Shape.prototype.move = function(x, y) {
* this.x += x;
* this.y += y;
* };
*
* _.forInRight(new Shape, function(value, key) {
* console.log(key);
* });
* // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
*/
function forInRight(object, callback, thisArg) {
var pairs = [];
forIn(object, function(value, key) {
pairs.push(key, value);
});
var length = pairs.length;
callback = baseCreateCallback(callback, thisArg, 3);
while (length--) {
if (callback(pairs[length--], pairs[length], object) === false) {
break;
}
}
return object;
}
module.exports = forInRight;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | 1 1 2 2 2 2 2 2 277 277 2 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
keys = require('./keys'),
objectTypes = require('../internals/objectTypes');
/**
* Iterates over own enumerable properties of an object, executing the callback
* for each property. The callback is bound to `thisArg` and invoked with three
* arguments; (value, key, object). Callbacks may exit iteration early by
* explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* console.log(key);
* });
* // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
*/
var forOwn = function(collection, callback, thisArg) {
var index, iterable = collection, result = iterable;
Iif (!iterable) return result;
Iif (!objectTypes[typeof iterable]) return result;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
Iif (callback(iterable[index], index, collection) === false) return result;
}
return result
};
module.exports = forOwn;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
keys = require('./keys');
/**
* This method is like `_.forOwn` except that it iterates over elements
* of a `collection` in the opposite order.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* console.log(key);
* });
* // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
*/
function forOwnRight(object, callback, thisArg) {
var props = keys(object),
length = props.length;
callback = baseCreateCallback(callback, thisArg, 3);
while (length--) {
var key = props[length];
if (callback(object[key], key, object) === false) {
break;
}
}
return object;
}
module.exports = forOwnRight;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 1 1 2 2 136 136 2 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var forIn = require('./forIn'),
isFunction = require('./isFunction');
/**
* Creates a sorted array of property names of all enumerable properties,
* own and inherited, of `object` that have function values.
*
* @static
* @memberOf _
* @alias methods
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names that have function values.
* @example
*
* _.functions(_);
* // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
*/
function functions(object) {
var result = [];
forIn(object, function(value, key) {
Eif (isFunction(value)) {
result.push(key);
}
});
return result.sort();
}
module.exports = functions;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Used for native method references */
var objectProto = Object.prototype;
/** Native method shortcuts */
var hasOwnProperty = objectProto.hasOwnProperty;
/**
* Checks if the specified property name exists as a direct property of `object`,
* instead of an inherited property.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @param {string} key The name of the property to check.
* @returns {boolean} Returns `true` if key is a direct property, else `false`.
* @example
*
* _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
* // => true
*/
function has(object, key) {
return object ? hasOwnProperty.call(object, key) : false;
}
module.exports = has;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 1 1 1 1 5 5 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var keys = require('./keys');
/**
* Creates an object composed of the inverted keys and values of the given object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to invert.
* @returns {Object} Returns the created inverted object.
* @example
*
* _.invert({ 'first': 'fred', 'second': 'barney' });
* // => { 'fred': 'first', 'barney': 'second' }
*/
function invert(object) {
var index = -1,
props = keys(object),
length = props.length,
result = {};
while (++index < length) {
var key = props[index];
result[object[key]] = key;
}
return result;
}
module.exports = invert;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/**
* Checks if `value` is an `arguments` object.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
* @example
*
* (function() { return _.isArguments(arguments); })(1, 2, 3);
* // => true
*
* _.isArguments([1, 2, 3]);
* // => false
*/
function isArguments(value) {
return value && typeof value == 'object' && typeof value.length == 'number' &&
toString.call(value) == argsClass || false;
}
module.exports = isArguments;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 1 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNative = require('../internals/isNative');
/** `Object#toString` result shortcuts */
var arrayClass = '[object Array]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray;
/**
* Checks if `value` is an array.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an array, else `false`.
* @example
*
* (function() { return _.isArray(arguments); })();
* // => false
*
* _.isArray([1, 2, 3]);
* // => true
*/
var isArray = nativeIsArray || function(value) {
return value && typeof value == 'object' && typeof value.length == 'number' &&
toString.call(value) == arrayClass || false;
};
module.exports = isArray;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** `Object#toString` result shortcuts */
var boolClass = '[object Boolean]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/**
* Checks if `value` is a boolean value.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
* @example
*
* _.isBoolean(null);
* // => false
*/
function isBoolean(value) {
return value === true || value === false ||
value && typeof value == 'object' && toString.call(value) == boolClass || false;
}
module.exports = isBoolean;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** `Object#toString` result shortcuts */
var dateClass = '[object Date]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/**
* Checks if `value` is a date.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a date, else `false`.
* @example
*
* _.isDate(new Date);
* // => true
*/
function isDate(value) {
return value && typeof value == 'object' && toString.call(value) == dateClass || false;
}
module.exports = isDate;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Checks if `value` is a DOM element.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
* @example
*
* _.isElement(document.body);
* // => true
*/
function isElement(value) {
return value && value.nodeType === 1 || false;
}
module.exports = isElement;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var forOwn = require('./forOwn'),
isFunction = require('./isFunction');
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
arrayClass = '[object Array]',
objectClass = '[object Object]',
stringClass = '[object String]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/**
* Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
* length of `0` and objects with no own enumerable properties are considered
* "empty".
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object|string} value The value to inspect.
* @returns {boolean} Returns `true` if the `value` is empty, else `false`.
* @example
*
* _.isEmpty([1, 2, 3]);
* // => false
*
* _.isEmpty({});
* // => true
*
* _.isEmpty('');
* // => true
*/
function isEmpty(value) {
var result = true;
if (!value) {
return result;
}
var className = toString.call(value),
length = value.length;
if ((className == arrayClass || className == stringClass || className == argsClass ) ||
(className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
return !length;
}
forOwn(value, function() {
return (result = false);
});
return result;
}
module.exports = isEmpty;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
baseIsEqual = require('../internals/baseIsEqual');
/**
* Performs a deep comparison between two values to determine if they are
* equivalent to each other. If a callback is provided it will be executed
* to compare values. If the callback returns `undefined` comparisons will
* be handled by the method instead. The callback is bound to `thisArg` and
* invoked with two arguments; (a, b).
*
* @static
* @memberOf _
* @category Objects
* @param {*} a The value to compare.
* @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* var object = { 'name': 'fred' };
* var copy = { 'name': 'fred' };
*
* object == copy;
* // => false
*
* _.isEqual(object, copy);
* // => true
*
* var words = ['hello', 'goodbye'];
* var otherWords = ['hi', 'goodbye'];
*
* _.isEqual(words, otherWords, function(a, b) {
* var reGreet = /^(?:hello|hi)$/i,
* aGreet = _.isString(a) && reGreet.test(a),
* bGreet = _.isString(b) && reGreet.test(b);
*
* return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
* });
* // => true
*/
function isEqual(a, b, callback, thisArg) {
return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
}
module.exports = isEqual;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeIsFinite = global.isFinite,
nativeIsNaN = global.isNaN;
/**
* Checks if `value` is, or can be coerced to, a finite number.
*
* Note: This is not the same as native `isFinite` which will return true for
* booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is finite, else `false`.
* @example
*
* _.isFinite(-101);
* // => true
*
* _.isFinite('10');
* // => true
*
* _.isFinite(true);
* // => false
*
* _.isFinite('');
* // => false
*
* _.isFinite(Infinity);
* // => false
*/
function isFinite(value) {
return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
}
module.exports = isFinite;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 1 138 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Checks if `value` is a function.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a function, else `false`.
* @example
*
* _.isFunction(_);
* // => true
*/
function isFunction(value) {
return typeof value == 'function';
}
module.exports = isFunction;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNumber = require('./isNumber');
/**
* Checks if `value` is `NaN`.
*
* Note: This is not the same as native `isNaN` which will return `true` for
* `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
* @example
*
* _.isNaN(NaN);
* // => true
*
* _.isNaN(new Number(NaN));
* // => true
*
* isNaN(undefined);
* // => true
*
* _.isNaN(undefined);
* // => false
*/
function isNaN(value) {
// `NaN` as a primitive is the only value that is not equal to itself
// (perform the [[Class]] check first to avoid errors with some host objects in IE)
return isNumber(value) && value != +value;
}
module.exports = isNaN;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Checks if `value` is `null`.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
* @example
*
* _.isNull(null);
* // => true
*
* _.isNull(undefined);
* // => false
*/
function isNull(value) {
return value === null;
}
module.exports = isNull;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** `Object#toString` result shortcuts */
var numberClass = '[object Number]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/**
* Checks if `value` is a number.
*
* Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a number, else `false`.
* @example
*
* _.isNumber(8.4 * 5);
* // => true
*/
function isNumber(value) {
return typeof value == 'number' ||
value && typeof value == 'object' && toString.call(value) == numberClass || false;
}
module.exports = isNumber;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 1 1 6 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var objectTypes = require('../internals/objectTypes');
/**
* Checks if `value` is the language type of Object.
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(1);
* // => false
*/
function isObject(value) {
// check if the value is the ECMAScript language type of Object
// http://es5.github.io/#x8
// and avoid a V8 bug
// http://code.google.com/p/v8/issues/detail?id=2291
return !!(value && objectTypes[typeof value]);
}
module.exports = isObject;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 1 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNative = require('../internals/isNative'),
shimIsPlainObject = require('../internals/shimIsPlainObject');
/** `Object#toString` result shortcuts */
var objectClass = '[object Object]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Native method shortcuts */
var getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf;
/**
* Checks if `value` is an object created by the `Object` constructor.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* _.isPlainObject(new Shape);
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
* _.isPlainObject({ 'x': 0, 'y': 0 });
* // => true
*/
var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
if (!(value && toString.call(value) == objectClass)) {
return false;
}
var valueOf = value.valueOf,
objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
return objProto
? (value == objProto || getPrototypeOf(value) == objProto)
: shimIsPlainObject(value);
};
module.exports = isPlainObject;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** `Object#toString` result shortcuts */
var regexpClass = '[object RegExp]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/**
* Checks if `value` is a regular expression.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
* @example
*
* _.isRegExp(/fred/);
* // => true
*/
function isRegExp(value) {
return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
}
module.exports = isRegExp;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** `Object#toString` result shortcuts */
var stringClass = '[object String]';
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/**
* Checks if `value` is a string.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a string, else `false`.
* @example
*
* _.isString('fred');
* // => true
*/
function isString(value) {
return typeof value == 'string' ||
value && typeof value == 'object' && toString.call(value) == stringClass || false;
}
module.exports = isString;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Checks if `value` is `undefined`.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
* @example
*
* _.isUndefined(void 0);
* // => true
*/
function isUndefined(value) {
return typeof value == 'undefined';
}
module.exports = isUndefined;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 1 1 1 5 5 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNative = require('../internals/isNative'),
isObject = require('./isObject'),
shimKeys = require('../internals/shimKeys');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys;
/**
* Creates an array composed of the own enumerable property names of an object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names.
* @example
*
* _.keys({ 'one': 1, 'two': 2, 'three': 3 });
* // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
*/
var keys = !nativeKeys ? shimKeys : function(object) {
Iif (!isObject(object)) {
return [];
}
return nativeKeys(object);
};
module.exports = keys;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var createCallback = require('../functions/createCallback'),
forOwn = require('./forOwn');
/**
* Creates an object with the same keys as `object` and values generated by
* running each own enumerable property of `object` through the callback.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new object with values of the results of each `callback` execution.
* @example
*
* _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
* // => { 'a': 3, 'b': 6, 'c': 9 }
*
* var characters = {
* 'fred': { 'name': 'fred', 'age': 40 },
* 'pebbles': { 'name': 'pebbles', 'age': 1 }
* };
*
* // using "_.pluck" callback shorthand
* _.mapValues(characters, 'age');
* // => { 'fred': 40, 'pebbles': 1 }
*/
function mapValues(object, callback, thisArg) {
var result = {};
callback = createCallback(callback, thisArg, 3);
forOwn(object, function(value, key, object) {
result[key] = callback(value, key, object);
});
return result;
}
module.exports = mapValues;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback'),
baseMerge = require('../internals/baseMerge'),
getArray = require('../internals/getArray'),
isObject = require('./isObject'),
releaseArray = require('../internals/releaseArray'),
slice = require('../internals/slice');
/**
* Recursively merges own enumerable properties of the source object(s), that
* don't resolve to `undefined` into the destination object. Subsequent sources
* will overwrite property assignments of previous sources. If a callback is
* provided it will be executed to produce the merged values of the destination
* and source properties. If the callback returns `undefined` merging will
* be handled by the method instead. The callback is bound to `thisArg` and
* invoked with two arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param {Function} [callback] The function to customize merging properties.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
* @example
*
* var names = {
* 'characters': [
* { 'name': 'barney' },
* { 'name': 'fred' }
* ]
* };
*
* var ages = {
* 'characters': [
* { 'age': 36 },
* { 'age': 40 }
* ]
* };
*
* _.merge(names, ages);
* // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
*
* var food = {
* 'fruits': ['apple'],
* 'vegetables': ['beet']
* };
*
* var otherFood = {
* 'fruits': ['banana'],
* 'vegetables': ['carrot']
* };
*
* _.merge(food, otherFood, function(a, b) {
* return _.isArray(a) ? a.concat(b) : undefined;
* });
* // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
*/
function merge(object) {
var args = arguments,
length = 2;
if (!isObject(object)) {
return object;
}
// allows working with `_.reduce` and `_.reduceRight` without using
// their `index` and `collection` arguments
if (typeof args[2] != 'number') {
length = args.length;
}
if (length > 3 && typeof args[length - 2] == 'function') {
var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
} else if (length > 2 && typeof args[length - 1] == 'function') {
callback = args[--length];
}
var sources = slice(arguments, 1, length),
index = -1,
stackA = getArray(),
stackB = getArray();
while (++index < length) {
baseMerge(object, sources[index], callback, stackA, stackB);
}
releaseArray(stackA);
releaseArray(stackB);
return object;
}
module.exports = merge;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseDifference = require('../internals/baseDifference'),
baseFlatten = require('../internals/baseFlatten'),
createCallback = require('../functions/createCallback'),
forIn = require('./forIn');
/**
* Creates a shallow clone of `object` excluding the specified properties.
* Property names may be specified as individual arguments or as arrays of
* property names. If a callback is provided it will be executed for each
* property of `object` omitting the properties the callback returns truey
* for. The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Function|...string|string[]} [callback] The properties to omit or the
* function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object without the omitted properties.
* @example
*
* _.omit({ 'name': 'fred', 'age': 40 }, 'age');
* // => { 'name': 'fred' }
*
* _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
* return typeof value == 'number';
* });
* // => { 'name': 'fred' }
*/
function omit(object, callback, thisArg) {
var result = {};
if (typeof callback != 'function') {
var props = [];
forIn(object, function(value, key) {
props.push(key);
});
props = baseDifference(props, baseFlatten(arguments, true, false, 1));
var index = -1,
length = props.length;
while (++index < length) {
var key = props[index];
result[key] = object[key];
}
} else {
callback = createCallback(callback, thisArg, 3);
forIn(object, function(value, key, object) {
if (!callback(value, key, object)) {
result[key] = value;
}
});
}
return result;
}
module.exports = omit;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var keys = require('./keys');
/**
* Creates a two dimensional array of an object's key-value pairs,
* i.e. `[[key1, value1], [key2, value2]]`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns new array of key-value pairs.
* @example
*
* _.pairs({ 'barney': 36, 'fred': 40 });
* // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
*/
function pairs(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
var key = props[index];
result[index] = [key, object[key]];
}
return result;
}
module.exports = pairs;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseFlatten = require('../internals/baseFlatten'),
createCallback = require('../functions/createCallback'),
forIn = require('./forIn'),
isObject = require('./isObject');
/**
* Creates a shallow clone of `object` composed of the specified properties.
* Property names may be specified as individual arguments or as arrays of
* property names. If a callback is provided it will be executed for each
* property of `object` picking the properties the callback returns truey
* for. The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Function|...string|string[]} [callback] The function called per
* iteration or property names to pick, specified as individual property
* names or arrays of property names.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object composed of the picked properties.
* @example
*
* _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
* // => { 'name': 'fred' }
*
* _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
* return key.charAt(0) != '_';
* });
* // => { 'name': 'fred' }
*/
function pick(object, callback, thisArg) {
var result = {};
if (typeof callback != 'function') {
var index = -1,
props = baseFlatten(arguments, true, false, 1),
length = isObject(object) ? props.length : 0;
while (++index < length) {
var key = props[index];
if (key in object) {
result[key] = object[key];
}
}
} else {
callback = createCallback(callback, thisArg, 3);
forIn(object, function(value, key, object) {
if (callback(value, key, object)) {
result[key] = value;
}
});
}
return result;
}
module.exports = pick;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreate = require('../internals/baseCreate'),
createCallback = require('../functions/createCallback'),
forEach = require('../collections/forEach'),
forOwn = require('./forOwn'),
isArray = require('./isArray');
/**
* An alternative to `_.reduce` this method transforms `object` to a new
* `accumulator` object which is the result of running each of its own
* enumerable properties through a callback, with each callback execution
* potentially mutating the `accumulator` object. The callback is bound to
* `thisArg` and invoked with four arguments; (accumulator, value, key, object).
* Callbacks may exit iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] The custom accumulator value.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
* num *= num;
* if (num % 2) {
* return result.push(num) < 3;
* }
* });
* // => [1, 9, 25]
*
* var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
* result[key] = num * 3;
* });
* // => { 'a': 3, 'b': 6, 'c': 9 }
*/
function transform(object, callback, accumulator, thisArg) {
var isArr = isArray(object);
if (accumulator == null) {
if (isArr) {
accumulator = [];
} else {
var ctor = object && object.constructor,
proto = ctor && ctor.prototype;
accumulator = baseCreate(proto);
}
}
if (callback) {
callback = createCallback(callback, thisArg, 4);
(isArr ? forEach : forOwn)(object, function(value, index, object) {
return callback(accumulator, value, index, object);
});
}
return accumulator;
}
module.exports = transform;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var keys = require('./keys');
/**
* Creates an array composed of the own enumerable property values of `object`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property values.
* @example
*
* _.values({ 'one': 1, 'two': 2, 'three': 3 });
* // => [1, 2, 3] (property order is not guaranteed across environments)
*/
function values(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
result[index] = object[props[index]];
}
return result;
}
module.exports = values;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| constant.js | 50% | (2 / 4) | 100% | (0 / 0) | 0% | (0 / 2) | 50% | (2 / 4) | |
| escape.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| identity.js | 66.67% | (2 / 3) | 100% | (0 / 0) | 0% | (0 / 1) | 66.67% | (2 / 3) | |
| mixin.js | 58.33% | (14 / 24) | 38.89% | (7 / 18) | 66.67% | (2 / 3) | 58.33% | (14 / 24) | |
| noConflict.js | 60% | (3 / 5) | 100% | (0 / 0) | 0% | (0 / 1) | 60% | (3 / 5) | |
| noop.js | 100% | (2 / 2) | 100% | (0 / 0) | 0% | (0 / 1) | 100% | (2 / 2) | |
| now.js | 75% | (3 / 4) | 66.67% | (2 / 3) | 0% | (0 / 1) | 75% | (3 / 4) | |
| parseInt.js | 85.71% | (6 / 7) | 16.67% | (1 / 6) | 0% | (0 / 1) | 85.71% | (6 / 7) | |
| property.js | 50% | (2 / 4) | 100% | (0 / 0) | 0% | (0 / 2) | 50% | (2 / 4) | |
| random.js | 17.39% | (4 / 23) | 0% | (0 / 25) | 0% | (0 / 1) | 17.39% | (4 / 23) | |
| result.js | 50% | (3 / 6) | 0% | (0 / 4) | 0% | (0 / 1) | 50% | (3 / 6) | |
| template.js | 17.5% | (7 / 40) | 0% | (0 / 30) | 0% | (0 / 2) | 17.5% | (7 / 40) | |
| templateSettings.js | 100% | (3 / 3) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (3 / 3) | |
| times.js | 33.33% | (3 / 9) | 0% | (0 / 2) | 0% | (0 / 1) | 33.33% | (3 / 9) | |
| unescape.js | 75% | (3 / 4) | 0% | (0 / 2) | 0% | (0 / 1) | 75% | (3 / 4) | |
| uniqueId.js | 60% | (3 / 5) | 0% | (0 / 2) | 0% | (0 / 1) | 60% | (3 / 5) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Creates a function that returns `value`.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} value The value to return from the new function.
* @returns {Function} Returns the new function.
* @example
*
* var object = { 'name': 'fred' };
* var getter = _.constant(object);
* getter() === object;
* // => true
*/
function constant(value) {
return function() {
return value;
};
}
module.exports = constant;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var escapeHtmlChar = require('../internals/escapeHtmlChar'),
keys = require('../objects/keys'),
reUnescapedHtml = require('../internals/reUnescapedHtml');
/**
* Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
* corresponding HTML entities.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} string The string to escape.
* @returns {string} Returns the escaped string.
* @example
*
* _.escape('Fred, Wilma, & Pebbles');
* // => 'Fred, Wilma, & Pebbles'
*/
function escape(string) {
return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
}
module.exports = escape;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* This method returns the first argument provided to it.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} value Any value.
* @returns {*} Returns `value`.
* @example
*
* var object = { 'name': 'fred' };
* _.identity(object) === object;
* // => true
*/
function identity(value) {
return value;
}
module.exports = identity;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 1 1 1 1 2 2 1 1 2 2 136 136 136 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var forEach = require('../collections/forEach'),
functions = require('../objects/functions'),
isFunction = require('../objects/isFunction'),
isObject = require('../objects/isObject');
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Native method shortcuts */
var push = arrayRef.push;
/**
* Adds function properties of a source object to the destination object.
* If `object` is a function methods will be added to its prototype as well.
*
* @static
* @memberOf _
* @category Utilities
* @param {Function|Object} [object=lodash] object The destination object.
* @param {Object} source The object of functions to add.
* @param {Object} [options] The options object.
* @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
* @example
*
* function capitalize(string) {
* return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
* }
*
* _.mixin({ 'capitalize': capitalize });
* _.capitalize('fred');
* // => 'Fred'
*
* _('fred').capitalize().value();
* // => 'Fred'
*
* _.mixin({ 'capitalize': capitalize }, { 'chain': false });
* _('fred').capitalize();
* // => 'Fred'
*/
function mixin(object, source, options) {
var chain = true,
methodNames = source && functions(source);
if (options === false) {
chain = false;
} else Iif (isObject(options) && 'chain' in options) {
chain = options.chain;
}
var ctor = object,
isFunc = isFunction(ctor);
forEach(methodNames, function(methodName) {
var func = object[methodName] = source[methodName];
Eif (isFunc) {
ctor.prototype[methodName] = function() {
var chainAll = this.__chain__,
value = this.__wrapped__,
args = [value];
push.apply(args, arguments);
var result = func.apply(object, args);
if (chain || chainAll) {
if (value === result && isObject(result)) {
return this;
}
result = new ctor(result);
result.__chain__ = chainAll;
}
return result;
};
}
});
}
module.exports = mixin;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Used to restore the original `_` reference in `noConflict` */
var oldDash = global._;
/**
* Reverts the '_' variable to its previous value and returns a reference to
* the `lodash` function.
*
* @static
* @memberOf _
* @category Utilities
* @returns {Function} Returns the `lodash` function.
* @example
*
* var lodash = _.noConflict();
*/
function noConflict() {
global._ = oldDash;
return this;
}
module.exports = noConflict;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* A no-operation function.
*
* @static
* @memberOf _
* @category Utilities
* @example
*
* var object = { 'name': 'fred' };
* _.noop(object) === undefined;
* // => true
*/
function noop() {
// no operation performed
}
module.exports = noop;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isNative = require('../internals/isNative');
/**
* Gets the number of milliseconds that have elapsed since the Unix epoch
* (1 January 1970 00:00:00 UTC).
*
* @static
* @memberOf _
* @category Utilities
* @example
*
* var stamp = _.now();
* _.defer(function() { console.log(_.now() - stamp); });
* // => logs the number of milliseconds it took for the deferred function to be called
*/
var now = isNative(now = Date.now) && now || function() {
return new Date().getTime();
};
module.exports = now;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isString = require('../objects/isString');
/** Used to detect and test whitespace */
var whitespace = (
// whitespace
' \t\x0B\f\xA0\ufeff' +
// line terminators
'\n\r\u2028\u2029' +
// unicode category "Zs" space separators
'\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
);
/** Used to match leading whitespace and zeros to be removed */
var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeParseInt = global.parseInt;
/**
* Converts the given value into an integer of the specified radix.
* If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
* `value` is a hexadecimal, in which case a `radix` of `16` is used.
*
* Note: This method avoids differences in native ES3 and ES5 `parseInt`
* implementations. See http://es5.github.io/#E.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} value The value to parse.
* @param {number} [radix] The radix used to interpret the value to parse.
* @returns {number} Returns the new integer value.
* @example
*
* _.parseInt('08');
* // => 8
*/
var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
// Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
};
module.exports = parseInt;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/**
* Creates a "_.pluck" style function, which returns the `key` value of a
* given object.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} key The name of the property to retrieve.
* @returns {Function} Returns the new function.
* @example
*
* var characters = [
* { 'name': 'fred', 'age': 40 },
* { 'name': 'barney', 'age': 36 }
* ];
*
* var getName = _.property('name');
*
* _.map(characters, getName);
* // => ['barney', 'fred']
*
* _.sortBy(characters, getName);
* // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }]
*/
function property(key) {
return function(object) {
return object[key];
};
}
module.exports = property;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseRandom = require('../internals/baseRandom');
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeMin = Math.min,
nativeRandom = Math.random;
/**
* Produces a random number between `min` and `max` (inclusive). If only one
* argument is provided a number between `0` and the given number will be
* returned. If `floating` is truey or either `min` or `max` are floats a
* floating-point number will be returned instead of an integer.
*
* @static
* @memberOf _
* @category Utilities
* @param {number} [min=0] The minimum possible value.
* @param {number} [max=1] The maximum possible value.
* @param {boolean} [floating=false] Specify returning a floating-point number.
* @returns {number} Returns a random number.
* @example
*
* _.random(0, 5);
* // => an integer between 0 and 5
*
* _.random(5);
* // => also an integer between 0 and 5
*
* _.random(5, true);
* // => a floating-point number between 0 and 5
*
* _.random(1.2, 5.2);
* // => a floating-point number between 1.2 and 5.2
*/
function random(min, max, floating) {
var noMin = min == null,
noMax = max == null;
if (floating == null) {
if (typeof min == 'boolean' && noMax) {
floating = min;
min = 1;
}
else if (!noMax && typeof max == 'boolean') {
floating = max;
noMax = true;
}
}
if (noMin && noMax) {
max = 1;
}
min = +min || 0;
if (noMax) {
max = min;
min = 0;
} else {
max = +max || 0;
}
if (floating || min % 1 || max % 1) {
var rand = nativeRandom();
return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
}
return baseRandom(min, max);
}
module.exports = random;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var isFunction = require('../objects/isFunction');
/**
* Resolves the value of property `key` on `object`. If `key` is a function
* it will be invoked with the `this` binding of `object` and its result returned,
* else the property value is returned. If `object` is falsey then `undefined`
* is returned.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} object The object to inspect.
* @param {string} key The name of the property to resolve.
* @returns {*} Returns the resolved value.
* @example
*
* var object = {
* 'cheese': 'crumpets',
* 'stuff': function() {
* return 'nonsense';
* }
* };
*
* _.result(object, 'cheese');
* // => 'crumpets'
*
* _.result(object, 'stuff');
* // => 'nonsense'
*/
function result(object, key) {
if (object) {
var value = object[key];
return isFunction(value) ? object[key]() : value;
}
}
module.exports = result;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | 1 1 1 1 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var defaults = require('../objects/defaults'),
escape = require('./escape'),
escapeStringChar = require('../internals/escapeStringChar'),
keys = require('../objects/keys'),
reInterpolate = require('../internals/reInterpolate'),
templateSettings = require('./templateSettings'),
values = require('../objects/values');
/** Used to match empty string literals in compiled template source */
var reEmptyStringLeading = /\b__p \+= '';/g,
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
/**
* Used to match ES6 template delimiters
* http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
*/
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
/** Used to ensure capturing order of template delimiters */
var reNoMatch = /($^)/;
/** Used to match unescaped characters in compiled string literals */
var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
/**
* A micro-templating method that handles arbitrary delimiters, preserves
* whitespace, and correctly escapes quotes within interpolated code.
*
* Note: In the development build, `_.template` utilizes sourceURLs for easier
* debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
*
* For more information on precompiling templates see:
* http://lodash.com/custom-builds
*
* For more information on Chrome extension sandboxes see:
* http://developer.chrome.com/stable/extensions/sandboxingEval.html
*
* @static
* @memberOf _
* @category Utilities
* @param {string} text The template text.
* @param {Object} data The data object used to populate the text.
* @param {Object} [options] The options object.
* @param {RegExp} [options.escape] The "escape" delimiter.
* @param {RegExp} [options.evaluate] The "evaluate" delimiter.
* @param {Object} [options.imports] An object to import into the template as local variables.
* @param {RegExp} [options.interpolate] The "interpolate" delimiter.
* @param {string} [sourceURL] The sourceURL of the template's compiled source.
* @param {string} [variable] The data object variable name.
* @returns {Function|string} Returns a compiled function when no `data` object
* is given, else it returns the interpolated text.
* @example
*
* // using the "interpolate" delimiter to create a compiled template
* var compiled = _.template('hello <%= name %>');
* compiled({ 'name': 'fred' });
* // => 'hello fred'
*
* // using the "escape" delimiter to escape HTML in data property values
* _.template('<b><%- value %></b>', { 'value': '<script>' });
* // => '<b><script></b>'
*
* // using the "evaluate" delimiter to generate HTML
* var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
* _.template(list, { 'people': ['fred', 'barney'] });
* // => '<li>fred</li><li>barney</li>'
*
* // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
* _.template('hello ${ name }', { 'name': 'pebbles' });
* // => 'hello pebbles'
*
* // using the internal `print` function in "evaluate" delimiters
* _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
* // => 'hello barney!'
*
* // using a custom template delimiters
* _.templateSettings = {
* 'interpolate': /{{([\s\S]+?)}}/g
* };
*
* _.template('hello {{ name }}!', { 'name': 'mustache' });
* // => 'hello mustache!'
*
* // using the `imports` option to import jQuery
* var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
* _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
* // => '<li>fred</li><li>barney</li>'
*
* // using the `sourceURL` option to specify a custom sourceURL for the template
* var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
* compiled(data);
* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
*
* // using the `variable` option to ensure a with-statement isn't used in the compiled template
* var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
* compiled.source;
* // => function(data) {
* var __t, __p = '', __e = _.escape;
* __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
* return __p;
* }
*
* // using the `source` property to inline compiled templates for meaningful
* // line numbers in error messages and a stack trace
* fs.writeFileSync(path.join(cwd, 'jst.js'), '\
* var JST = {\
* "main": ' + _.template(mainText).source + '\
* };\
* ');
*/
function template(text, data, options) {
// based on John Resig's `tmpl` implementation
// http://ejohn.org/blog/javascript-micro-templating/
// and Laura Doktorova's doT.js
// https://github.com/olado/doT
var settings = templateSettings.imports._.templateSettings || templateSettings;
text = String(text || '');
// avoid missing dependencies when `iteratorTemplate` is not defined
options = defaults({}, options, settings);
var imports = defaults({}, options.imports, settings.imports),
importsKeys = keys(imports),
importsValues = values(imports);
var isEvaluating,
index = 0,
interpolate = options.interpolate || reNoMatch,
source = "__p += '";
// compile the regexp to match each delimiter
var reDelimiters = RegExp(
(options.escape || reNoMatch).source + '|' +
interpolate.source + '|' +
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
(options.evaluate || reNoMatch).source + '|$'
, 'g');
text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
interpolateValue || (interpolateValue = esTemplateValue);
// escape characters that cannot be included in string literals
source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
// replace delimiters with snippets
if (escapeValue) {
source += "' +\n__e(" + escapeValue + ") +\n'";
}
if (evaluateValue) {
isEvaluating = true;
source += "';\n" + evaluateValue + ";\n__p += '";
}
if (interpolateValue) {
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
}
index = offset + match.length;
// the JS engine embedded in Adobe products requires returning the `match`
// string in order to produce the correct `offset` value
return match;
});
source += "';\n";
// if `variable` is not specified, wrap a with-statement around the generated
// code to add the data object to the top of the scope chain
var variable = options.variable,
hasVariable = variable;
if (!hasVariable) {
variable = 'obj';
source = 'with (' + variable + ') {\n' + source + '\n}\n';
}
// cleanup code by stripping empty strings
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
.replace(reEmptyStringMiddle, '$1')
.replace(reEmptyStringTrailing, '$1;');
// frame code as the function body
source = 'function(' + variable + ') {\n' +
(hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
"var __t, __p = '', __e = _.escape" +
(isEvaluating
? ', __j = Array.prototype.join;\n' +
"function print() { __p += __j.call(arguments, '') }\n"
: ';\n'
) +
source +
'return __p\n}';
try {
var result = Function(importsKeys, 'return ' + source ).apply(undefined, importsValues);
} catch(e) {
e.source = source;
throw e;
}
if (data) {
return result(data);
}
// provide the compiled function's source by its `toString` method, in
// supported environments, or the `source` property as a convenience for
// inlining compiled templates during the build process
result.source = source;
return result;
}
module.exports = template;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var escape = require('./escape'),
reInterpolate = require('../internals/reInterpolate');
/**
* By default, the template delimiters used by Lo-Dash are similar to those in
* embedded Ruby (ERB). Change the following template settings to use alternative
* delimiters.
*
* @static
* @memberOf _
* @type Object
*/
var templateSettings = {
/**
* Used to detect `data` property values to be HTML-escaped.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'escape': /<%-([\s\S]+?)%>/g,
/**
* Used to detect code to be evaluated.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'evaluate': /<%([\s\S]+?)%>/g,
/**
* Used to detect `data` property values to inject.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'interpolate': reInterpolate,
/**
* Used to reference the data object in the template text.
*
* @memberOf _.templateSettings
* @type string
*/
'variable': '',
/**
* Used to import variables into the compiled template.
*
* @memberOf _.templateSettings
* @type Object
*/
'imports': {
/**
* A reference to the `lodash` function.
*
* @memberOf _.templateSettings.imports
* @type Function
*/
'_': { 'escape': escape }
}
};
module.exports = templateSettings;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var baseCreateCallback = require('../internals/baseCreateCallback');
/**
* Executes the callback `n` times, returning an array of the results
* of each callback execution. The callback is bound to `thisArg` and invoked
* with one argument; (index).
*
* @static
* @memberOf _
* @category Utilities
* @param {number} n The number of times to execute the callback.
* @param {Function} callback The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns an array of the results of each `callback` execution.
* @example
*
* var diceRolls = _.times(3, _.partial(_.random, 1, 6));
* // => [3, 6, 4]
*
* _.times(3, function(n) { mage.castSpell(n); });
* // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
*
* _.times(3, function(n) { this.cast(n); }, mage);
* // => also calls `mage.castSpell(n)` three times
*/
function times(n, callback, thisArg) {
n = (n = +n) > -1 ? n : 0;
var index = -1,
result = Array(n);
callback = baseCreateCallback(callback, thisArg, 1);
while (++index < n) {
result[index] = callback(index);
}
return result;
}
module.exports = times;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
var keys = require('../objects/keys'),
reEscapedHtml = require('../internals/reEscapedHtml'),
unescapeHtmlChar = require('../internals/unescapeHtmlChar');
/**
* The inverse of `_.escape` this method converts the HTML entities
* `&`, `<`, `>`, `"`, and `'` in `string` to their
* corresponding characters.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} string The string to unescape.
* @returns {string} Returns the unescaped string.
* @example
*
* _.unescape('Fred, Barney & Pebbles');
* // => 'Fred, Barney & Pebbles'
*/
function unescape(string) {
return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
}
module.exports = unescape;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 1 1 1 | /**
* Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modularize modern exports="node" -o ./modern/`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license <http://lodash.com/license>
*/
/** Used to generate unique IDs */
var idCounter = 0;
/**
* Generates a unique ID. If `prefix` is provided the ID will be appended to it.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} [prefix] The value to prefix the ID with.
* @returns {string} Returns the unique ID.
* @example
*
* _.uniqueId('contact_');
* // => 'contact_104'
*
* _.uniqueId();
* // => '105'
*/
function uniqueId(prefix) {
var id = ++idCounter;
return String(prefix == null ? '' : prefix) + id;
}
module.exports = uniqueId;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| dom-parser.js | 13.82% | (17 / 123) | 1.37% | (1 / 73) | 3.13% | (1 / 32) | 14.05% | (17 / 121) | |
| dom.js | 21.35% | (130 / 609) | 2.77% | (7 / 253) | 1.8% | (2 / 111) | 21.49% | (130 / 605) | |
| sax.js | 10.62% | (36 / 339) | 1.22% | (2 / 164) | 3.7% | (1 / 27) | 10.68% | (36 / 337) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 | function DOMParser(options){ this.options = options ||{locator:{}}; } DOMParser.prototype.parseFromString = function(source,mimeType){ var options = this.options; var sax = new XMLReader(); var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler var errorHandler = options.errorHandler; var locator = options.locator; var defaultNSMap = options.xmlns||{}; var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"} if(locator){ domBuilder.setDocumentLocator(locator) } sax.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator); sax.domBuilder = options.domBuilder || domBuilder; if(/\/x?html?$/.test(mimeType)){ entityMap.nbsp = '\xa0'; entityMap.copy = '\xa9'; defaultNSMap['']= 'http://www.w3.org/1999/xhtml'; } if(source){ sax.parse(source,defaultNSMap,entityMap); }else{ sax.errorHandler.error("invalid document source"); } return domBuilder.document; } function buildErrorHandler(errorImpl,domBuilder,locator){ if(!errorImpl){ if(domBuilder instanceof DOMHandler){ return domBuilder; } errorImpl = domBuilder ; } var errorHandler = {} var isCallback = errorImpl instanceof Function; locator = locator||{} function build(key){ var fn = errorImpl[key]; if(!fn){ if(isCallback){ fn = errorImpl.length == 2?function(msg){errorImpl(key,msg)}:errorImpl; }else{ var i=arguments.length; while(--i){ if(fn = errorImpl[arguments[i]]){ break; } } } } errorHandler[key] = fn && function(msg){ fn(msg+_locator(locator)); }||function(){}; } build('warning','warn'); build('error','warn','warning'); build('fatalError','warn','warning','error'); return errorHandler; } /** * +ContentHandler+ErrorHandler * +LexicalHandler+EntityResolver2 * -DeclHandler-DTDHandler * * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2 * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html */ function DOMHandler() { this.cdata = false; } function position(locator,node){ node.lineNumber = locator.lineNumber; node.columnNumber = locator.columnNumber; } /** * @see org.xml.sax.ContentHandler#startDocument * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html */ DOMHandler.prototype = { startDocument : function() { this.document = new DOMImplementation().createDocument(null, null, null); if (this.locator) { this.document.documentURI = this.locator.systemId; } }, startElement:function(namespaceURI, localName, qName, attrs) { var doc = this.document; var el = doc.createElementNS(namespaceURI, qName||localName); var len = attrs.length; appendElement(this, el); this.currentElement = el; this.locator && position(this.locator,el) for (var i = 0 ; i < len; i++) { var namespaceURI = attrs.getURI(i); var value = attrs.getValue(i); var qName = attrs.getQName(i); var attr = doc.createAttributeNS(namespaceURI, qName); if( attr.getOffset){ position(attr.getOffset(1),attr) } attr.value = attr.nodeValue = value; el.setAttributeNode(attr) } }, endElement:function(namespaceURI, localName, qName) { var current = this.currentElement var tagName = current.tagName; this.currentElement = current.parentNode; }, startPrefixMapping:function(prefix, uri) { }, endPrefixMapping:function(prefix) { }, processingInstruction:function(target, data) { var ins = this.document.createProcessingInstruction(target, data); this.locator && position(this.locator,ins) appendElement(this, ins); }, ignorableWhitespace:function(ch, start, length) { }, characters:function(chars, start, length) { chars = _toString.apply(this,arguments) //console.log(chars) if(this.currentElement && chars){ if (this.cdata) { var charNode = this.document.createCDATASection(chars); this.currentElement.appendChild(charNode); } else { var charNode = this.document.createTextNode(chars); this.currentElement.appendChild(charNode); } this.locator && position(this.locator,charNode) } }, skippedEntity:function(name) { }, endDocument:function() { this.document.normalize(); }, setDocumentLocator:function (locator) { if(this.locator = locator){// && !('lineNumber' in locator)){ locator.lineNumber = 0; } }, //LexicalHandler comment:function(chars, start, length) { chars = _toString.apply(this,arguments) var comm = this.document.createComment(chars); this.locator && position(this.locator,comm) appendElement(this, comm); }, startCDATA:function() { //used in characters() methods this.cdata = true; }, endCDATA:function() { this.cdata = false; }, startDTD:function(name, publicId, systemId) { var impl = this.document.implementation; if (impl && impl.createDocumentType) { var dt = impl.createDocumentType(name, publicId, systemId); this.locator && position(this.locator,dt) appendElement(this, dt); } }, /** * @see org.xml.sax.ErrorHandler * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html */ warning:function(error) { console.warn(error,_locator(this.locator)); }, error:function(error) { console.error(error,_locator(this.locator)); }, fatalError:function(error) { console.error(error,_locator(this.locator)); throw error; } } function _locator(l){ if(l){ return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']' } } function _toString(chars,start,length){ if(typeof chars == 'string'){ return chars.substr(start,length) }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)") if(chars.length >= start+length || start){ return new java.lang.String(chars,start,length)+''; } return chars; } } /* * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html * used method of org.xml.sax.ext.LexicalHandler: * #comment(chars, start, length) * #startCDATA() * #endCDATA() * #startDTD(name, publicId, systemId) * * * IGNORED method of org.xml.sax.ext.LexicalHandler: * #endDTD() * #startEntity(name) * #endEntity(name) * * * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html * IGNORED method of org.xml.sax.ext.DeclHandler * #attributeDecl(eName, aName, type, mode, value) * #elementDecl(name, model) * #externalEntityDecl(name, publicId, systemId) * #internalEntityDecl(name, value) * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html * IGNORED method of org.xml.sax.EntityResolver2 * #resolveEntity(String name,String publicId,String baseURI,String systemId) * #resolveEntity(publicId, systemId) * #getExternalSubset(name, baseURI) * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html * IGNORED method of org.xml.sax.DTDHandler * #notationDecl(name, publicId, systemId) {}; * #unparsedEntityDecl(name, publicId, systemId, notationName) {}; */ "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){ DOMHandler.prototype[key] = function(){return null} }) /* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */ function appendElement (hander,node) { if (!hander.currentElement) { hander.document.appendChild(node); } else { hander.currentElement.appendChild(node); } }//appendChild and setAttributeNS are preformance key Eif(typeof require == 'function'){ var XMLReader = require('./sax').XMLReader; var DOMImplementation = exports.DOMImplementation = require('./dom').DOMImplementation; exports.XMLSerializer = require('./dom').XMLSerializer ; exports.DOMParser = DOMParser; } |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 | 1 3 39 1 14 14 14 14 14 1 14 6 6 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /*
* DOM Level 2
* Object DOMException
* @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
*/
function copy(src,dest){
for(var p in src){
dest[p] = src[p];
}
}
/**
^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
*/
function _extends(Class,Super){
var pt = Class.prototype;
Eif(Object.create){
var ppt = Object.create(Super.prototype)
pt.__proto__ = ppt;
}
Iif(!(pt instanceof Super)){
function t(){};
t.prototype = Super.prototype;
t = new t();
copy(pt,t);
Class.prototype = pt = t;
}
if(pt.constructor != Class){
Iif(typeof Class != 'function'){
console.error("unknow Class:"+Class)
}
pt.constructor = Class
}
}
var htmlns = 'http://www.w3.org/1999/xhtml' ;
// Node Types
var NodeType = {}
var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
var TEXT_NODE = NodeType.TEXT_NODE = 3;
var CDATA_SECTION_NODE = NodeType.CDATA_SECTION_NODE = 4;
var ENTITY_REFERENCE_NODE = NodeType.ENTITY_REFERENCE_NODE = 5;
var ENTITY_NODE = NodeType.ENTITY_NODE = 6;
var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
var COMMENT_NODE = NodeType.COMMENT_NODE = 8;
var DOCUMENT_NODE = NodeType.DOCUMENT_NODE = 9;
var DOCUMENT_TYPE_NODE = NodeType.DOCUMENT_TYPE_NODE = 10;
var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
var NOTATION_NODE = NodeType.NOTATION_NODE = 12;
// ExceptionCode
var ExceptionCode = {}
var ExceptionMessage = {};
var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1);
var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2);
var HIERARCHY_REQUEST_ERR = ExceptionCode.HIERARCHY_REQUEST_ERR = ((ExceptionMessage[3]="Hierarchy request error"),3);
var WRONG_DOCUMENT_ERR = ExceptionCode.WRONG_DOCUMENT_ERR = ((ExceptionMessage[4]="Wrong document"),4);
var INVALID_CHARACTER_ERR = ExceptionCode.INVALID_CHARACTER_ERR = ((ExceptionMessage[5]="Invalid character"),5);
var NO_DATA_ALLOWED_ERR = ExceptionCode.NO_DATA_ALLOWED_ERR = ((ExceptionMessage[6]="No data allowed"),6);
var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
var NOT_FOUND_ERR = ExceptionCode.NOT_FOUND_ERR = ((ExceptionMessage[8]="Not found"),8);
var NOT_SUPPORTED_ERR = ExceptionCode.NOT_SUPPORTED_ERR = ((ExceptionMessage[9]="Not supported"),9);
var INUSE_ATTRIBUTE_ERR = ExceptionCode.INUSE_ATTRIBUTE_ERR = ((ExceptionMessage[10]="Attribute in use"),10);
//level2
var INVALID_STATE_ERR = ExceptionCode.INVALID_STATE_ERR = ((ExceptionMessage[11]="Invalid state"),11);
var SYNTAX_ERR = ExceptionCode.SYNTAX_ERR = ((ExceptionMessage[12]="Syntax error"),12);
var INVALID_MODIFICATION_ERR = ExceptionCode.INVALID_MODIFICATION_ERR = ((ExceptionMessage[13]="Invalid modification"),13);
var NAMESPACE_ERR = ExceptionCode.NAMESPACE_ERR = ((ExceptionMessage[14]="Invalid namespace"),14);
var INVALID_ACCESS_ERR = ExceptionCode.INVALID_ACCESS_ERR = ((ExceptionMessage[15]="Invalid access"),15);
function DOMException(code, message) {
if(message instanceof Error){
var error = message;
}else{
error = this;
Error.call(this, ExceptionMessage[code]);
this.message = ExceptionMessage[code];
if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
}
error.code = code;
if(message) this.message = this.message + ": " + message;
return error;
};
DOMException.prototype = Error.prototype;
copy(ExceptionCode,DOMException)
/**
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
* The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
* The items in the NodeList are accessible via an integral index, starting from 0.
*/
function NodeList() {
};
NodeList.prototype = {
/**
* The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
* @standard level1
*/
length:0,
/**
* Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
* @standard level1
* @param index unsigned long
* Index into the collection.
* @return Node
* The node at the indexth position in the NodeList, or null if that is not a valid index.
*/
item: function(index) {
return this[index] || null;
}
};
function LiveNodeList(node,refresh){
this._node = node;
this._refresh = refresh
_updateLiveList(this);
}
function _updateLiveList(list){
var inc = list._node._inc || list._node.ownerDocument._inc;
if(list._inc != inc){
var ls = list._refresh(list._node);
//console.log(ls.length)
__set__(list,'length',ls.length);
copy(ls,list);
list._inc = inc;
}
}
LiveNodeList.prototype.item = function(i){
_updateLiveList(this);
return this[i];
}
_extends(LiveNodeList,NodeList);
/**
*
* Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes.
* NamedNodeMap objects in the DOM are live.
* used for attributes or DocumentType entities
*/
function NamedNodeMap() {
};
function _findNodeIndex(list,node){
var i = list.length;
while(i--){
if(list[i] === node){return i}
}
}
function _addNamedNode(el,list,newAttr,oldAttr){
if(oldAttr){
list[_findNodeIndex(list,oldAttr)] = newAttr;
}else{
list[list.length++] = newAttr;
}
if(el){
newAttr.ownerElement = el;
var doc = el.ownerDocument;
if(doc){
oldAttr && _onRemoveAttribute(doc,el,oldAttr);
_onAddAttribute(doc,el,newAttr);
}
}
}
function _removeNamedNode(el,list,attr){
var i = _findNodeIndex(list,attr);
if(i>=0){
var lastIndex = list.length-1
while(i<lastIndex){
list[i] = list[++i]
}
list.length = lastIndex;
if(el){
var doc = el.ownerDocument;
if(doc){
_onRemoveAttribute(doc,el,attr);
attr.ownerElement = null;
}
}
}else{
throw DOMException(NOT_FOUND_ERR,new Error())
}
}
NamedNodeMap.prototype = {
length:0,
item:NodeList.prototype.item,
getNamedItem: function(key) {
// if(key.indexOf(':')>0 || key == 'xmlns'){
// return null;
// }
var i = this.length;
while(i--){
var attr = this[i];
if(attr.nodeName == key){
return attr;
}
}
},
setNamedItem: function(attr) {
var el = attr.ownerElement;
if(el && el!=this._ownerElement){
throw new DOMException(INUSE_ATTRIBUTE_ERR);
}
var oldAttr = this.getNamedItem(attr.nodeName);
_addNamedNode(this._ownerElement,this,attr,oldAttr);
return oldAttr;
},
/* returns Node */
setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
var el = attr.ownerElement, oldAttr;
if(el && el!=this._ownerElement){
throw new DOMException(INUSE_ATTRIBUTE_ERR);
}
oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
_addNamedNode(this._ownerElement,this,attr,oldAttr);
return oldAttr;
},
/* returns Node */
removeNamedItem: function(key) {
var attr = this.getNamedItem(key);
_removeNamedNode(this._ownerElement,this,attr);
return attr;
},// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
//for level2
removeNamedItemNS:function(namespaceURI,localName){
var attr = this.getNamedItemNS(namespaceURI,localName);
_removeNamedNode(this._ownerElement,this,attr);
return attr;
},
getNamedItemNS: function(namespaceURI, localName) {
var i = this.length;
while(i--){
var node = this[i];
if(node.localName == localName && node.namespaceURI == namespaceURI){
return node;
}
}
return null;
}
};
/**
* @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
*/
function DOMImplementation(/* Object */ features) {
this._features = {};
if (features) {
for (var feature in features) {
this._features = features[feature];
}
}
};
DOMImplementation.prototype = {
hasFeature: function(/* string */ feature, /* string */ version) {
var versions = this._features[feature.toLowerCase()];
if (versions && (!version || version in versions)) {
return true;
} else {
return false;
}
},
// Introduced in DOM Level 2:
createDocument:function(namespaceURI, qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
var doc = new Document();
doc.doctype = doctype;
if(doctype){
doc.appendChild(doctype);
}
doc.implementation = this;
doc.childNodes = new NodeList();
if(qualifiedName){
var root = doc.createElementNS(namespaceURI,qualifiedName);
doc.appendChild(root);
}
return doc;
},
// Introduced in DOM Level 2:
createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
var node = new DocumentType();
node.name = qualifiedName;
node.nodeName = qualifiedName;
node.publicId = publicId;
node.systemId = systemId;
// Introduced in DOM Level 2:
//readonly attribute DOMString internalSubset;
//TODO:..
// readonly attribute NamedNodeMap entities;
// readonly attribute NamedNodeMap notations;
return node;
}
};
/**
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
*/
function Node() {
};
Node.prototype = {
firstChild : null,
lastChild : null,
previousSibling : null,
nextSibling : null,
attributes : null,
parentNode : null,
childNodes : null,
ownerDocument : null,
nodeValue : null,
namespaceURI : null,
prefix : null,
localName : null,
// Modified in DOM Level 2:
insertBefore:function(newChild, refChild){//raises
return _insertBefore(this,newChild,refChild);
},
replaceChild:function(newChild, oldChild){//raises
this.insertBefore(newChild,oldChild);
if(oldChild){
this.removeChild(oldChild);
}
},
removeChild:function(oldChild){
return _removeChild(this,oldChild);
},
appendChild:function(newChild){
return this.insertBefore(newChild,null);
},
hasChildNodes:function(){
return this.firstChild != null;
},
cloneNode:function(deep){
return cloneNode(this.ownerDocument||this,this,deep);
},
// Modified in DOM Level 2:
normalize:function(){
var child = this.firstChild;
while(child){
var next = child.nextSibling;
if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
this.removeChild(next);
child.appendData(next.data);
}else{
child.normalize();
child = next;
}
}
},
// Introduced in DOM Level 2:
isSupported:function(feature, version){
return this.ownerDocument.implementation.hasFeature(feature,version);
},
// Introduced in DOM Level 2:
hasAttributes:function(){
return this.attributes.length>0;
},
lookupPrefix:function(namespaceURI){
var el = this;
while(el){
var map = el._nsMap;
//console.dir(map)
if(map){
for(var n in map){
if(map[n] == namespaceURI){
return n;
}
}
}
el = el.nodeType == 2?el.ownerDocument : el.parentNode;
}
return null;
},
// Introduced in DOM Level 3:
lookupNamespaceURI:function(prefix){
var el = this;
while(el){
var map = el._nsMap;
//console.dir(map)
if(map){
if(prefix in map){
return map[prefix] ;
}
}
el = el.nodeType == 2?el.ownerDocument : el.parentNode;
}
return null;
},
// Introduced in DOM Level 3:
isDefaultNamespace:function(namespaceURI){
var prefix = this.lookupPrefix(namespaceURI);
return prefix == null;
}
};
function _xmlEncoder(c){
return c == '<' && '<' ||
c == '>' && '>' ||
c == '&' && '&' ||
c == '"' && '"' ||
'&#'+c.charCodeAt()+';'
}
copy(NodeType,Node);
copy(NodeType,Node.prototype);
/**
* @param callback return true for continue,false for break
* @return boolean true: break visit;
*/
function _visitNode(node,callback){
if(callback(node)){
return true;
}
if(node = node.firstChild){
do{
if(_visitNode(node,callback)){return true}
}while(node=node.nextSibling)
}
}
function Document(){
}
function _onAddAttribute(doc,el,newAttr){
doc && doc._inc++;
var ns = newAttr.namespaceURI ;
if(ns == 'http://www.w3.org/2000/xmlns/'){
//update namespace
el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value
}
}
function _onRemoveAttribute(doc,el,newAttr,remove){
doc && doc._inc++;
var ns = newAttr.namespaceURI ;
if(ns == 'http://www.w3.org/2000/xmlns/'){
//update namespace
delete el._nsMap[newAttr.prefix?newAttr.localName:'']
}
}
function _onUpdateChild(doc,el,newChild){
if(doc && doc._inc){
doc._inc++;
//update childNodes
var cs = el.childNodes;
if(newChild){
cs[cs.length++] = newChild;
}else{
//console.log(1)
var child = el.firstChild;
var i = 0;
while(child){
cs[i++] = child;
child =child.nextSibling;
}
cs.length = i;
}
}
}
/**
* attributes;
* children;
*
* writeable properties:
* nodeValue,Attr:value,CharacterData:data
* prefix
*/
function _removeChild(parentNode,child){
var previous = child.previousSibling;
var next = child.nextSibling;
if(previous){
previous.nextSibling = next;
}else{
parentNode.firstChild = next
}
if(next){
next.previousSibling = previous;
}else{
parentNode.lastChild = previous;
}
_onUpdateChild(parentNode.ownerDocument,parentNode);
return child;
}
/**
* preformance key(refChild == null)
*/
function _insertBefore(parentNode,newChild,nextChild){
var cp = newChild.parentNode;
if(cp){
cp.removeChild(newChild);//remove and update
}
if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
var newFirst = newChild.firstChild;
if (newFirst == null) {
return newChild;
}
var newLast = newChild.lastChild;
}else{
newFirst = newLast = newChild;
}
var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
newFirst.previousSibling = pre;
newLast.nextSibling = nextChild;
if(pre){
pre.nextSibling = newFirst;
}else{
parentNode.firstChild = newFirst;
}
if(nextChild == null){
parentNode.lastChild = newLast;
}else{
nextChild.previousSibling = newLast;
}
do{
newFirst.parentNode = parentNode;
}while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
_onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
//console.log(parentNode.lastChild.nextSibling == null)
if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
newChild.firstChild = newChild.lastChild = null;
}
return newChild;
}
function _appendSingleChild(parentNode,newChild){
var cp = newChild.parentNode;
if(cp){
var pre = parentNode.lastChild;
cp.removeChild(newChild);//remove and update
var pre = parentNode.lastChild;
}
var pre = parentNode.lastChild;
newChild.parentNode = parentNode;
newChild.previousSibling = pre;
newChild.nextSibling = null;
if(pre){
pre.nextSibling = newChild;
}else{
parentNode.firstChild = newChild;
}
parentNode.lastChild = newChild;
_onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
return newChild;
//console.log("__aa",parentNode.lastChild.nextSibling == null)
}
Document.prototype = {
//implementation : null,
nodeName : '#document',
nodeType : DOCUMENT_NODE,
doctype : null,
documentElement : null,
_inc : 1,
insertBefore : function(newChild, refChild){//raises
if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
var child = newChild.firstChild;
while(child){
var next = child.nextSibling;
this.insertBefore(child,refChild);
child = next;
}
return newChild;
}
if(this.documentElement == null && newChild.nodeType == 1){
this.documentElement = newChild;
}
return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
},
removeChild : function(oldChild){
if(this.documentElement == oldChild){
this.documentElement = null;
}
return _removeChild(this,oldChild);
},
// Introduced in DOM Level 2:
importNode : function(importedNode,deep){
return importNode(this,importedNode,deep);
},
// Introduced in DOM Level 2:
getElementById : function(id){
var rtv = null;
_visitNode(this.documentElement,function(node){
if(node.nodeType == 1){
if(node.getAttribute('id') == id){
rtv = node;
return true;
}
}
})
return rtv;
},
//document factory method:
createElement : function(tagName){
var node = new Element();
node.ownerDocument = this;
node.nodeName = tagName;
node.tagName = tagName;
node.childNodes = new NodeList();
var attrs = node.attributes = new NamedNodeMap();
attrs._ownerElement = node;
return node;
},
createDocumentFragment : function(){
var node = new DocumentFragment();
node.ownerDocument = this;
node.childNodes = new NodeList();
return node;
},
createTextNode : function(data){
var node = new Text();
node.ownerDocument = this;
node.appendData(data)
return node;
},
createComment : function(data){
var node = new Comment();
node.ownerDocument = this;
node.appendData(data)
return node;
},
createCDATASection : function(data){
var node = new CDATASection();
node.ownerDocument = this;
node.appendData(data)
return node;
},
createProcessingInstruction : function(target,data){
var node = new ProcessingInstruction();
node.ownerDocument = this;
node.tagName = node.target = target;
node.nodeValue= node.data = data;
return node;
},
createAttribute : function(name){
var node = new Attr();
node.ownerDocument = this;
node.name = name;
node.nodeName = name;
node.localName = name;
node.specified = true;
return node;
},
createEntityReference : function(name){
var node = new EntityReference();
node.ownerDocument = this;
node.nodeName = name;
return node;
},
// Introduced in DOM Level 2:
createElementNS : function(namespaceURI,qualifiedName){
var node = new Element();
var pl = qualifiedName.split(':');
var attrs = node.attributes = new NamedNodeMap();
node.childNodes = new NodeList();
node.ownerDocument = this;
node.nodeName = qualifiedName;
node.tagName = qualifiedName;
node.namespaceURI = namespaceURI;
if(pl.length == 2){
node.prefix = pl[0];
node.localName = pl[1];
}else{
//el.prefix = null;
node.localName = qualifiedName;
}
attrs._ownerElement = node;
return node;
},
// Introduced in DOM Level 2:
createAttributeNS : function(namespaceURI,qualifiedName){
var node = new Attr();
var pl = qualifiedName.split(':');
node.ownerDocument = this;
node.nodeName = qualifiedName;
node.name = qualifiedName;
node.namespaceURI = namespaceURI;
node.specified = true;
if(pl.length == 2){
node.prefix = pl[0];
node.localName = pl[1];
}else{
//el.prefix = null;
node.localName = qualifiedName;
}
return node;
}
};
_extends(Document,Node);
function Element() {
this._nsMap = {};
};
Element.prototype = {
nodeType : ELEMENT_NODE,
hasAttribute : function(name){
return this.getAttributeNode(name)!=null;
},
getAttribute : function(name){
var attr = this.getAttributeNode(name);
return attr && attr.value || '';
},
getAttributeNode : function(name){
return this.attributes.getNamedItem(name);
},
setAttribute : function(name, value){
var attr = this.ownerDocument.createAttribute(name);
attr.value = attr.nodeValue = "" + value;
this.setAttributeNode(attr)
},
removeAttribute : function(name){
var attr = this.getAttributeNode(name)
attr && this.removeAttributeNode(attr);
},
//four real opeartion method
appendChild:function(newChild){
if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
return this.insertBefore(newChild,null);
}else{
return _appendSingleChild(this,newChild);
}
},
setAttributeNode : function(newAttr){
return this.attributes.setNamedItem(newAttr);
},
setAttributeNodeNS : function(newAttr){
return this.attributes.setNamedItemNS(newAttr);
},
removeAttributeNode : function(oldAttr){
return this.attributes.removeNamedItem(oldAttr.nodeName);
},
//get real attribute name,and remove it by removeAttributeNode
removeAttributeNS : function(namespaceURI, localName){
var old = this.getAttributeNodeNS(namespaceURI, localName);
old && this.removeAttributeNode(old);
},
hasAttributeNS : function(namespaceURI, localName){
return this.getAttributeNodeNS(namespaceURI, localName)!=null;
},
getAttributeNS : function(namespaceURI, localName){
var attr = this.getAttributeNodeNS(namespaceURI, localName);
return attr && attr.value || '';
},
setAttributeNS : function(namespaceURI, qualifiedName, value){
var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
attr.value = attr.nodeValue = value;
this.setAttributeNode(attr)
},
getAttributeNodeNS : function(namespaceURI, localName){
return this.attributes.getNamedItemNS(namespaceURI, localName);
},
getElementsByTagName : function(tagName){
return new LiveNodeList(this,function(base){
var ls = [];
_visitNode(base,function(node){
if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
ls.push(node);
}
});
return ls;
});
},
getElementsByTagNameNS : function(namespaceURI, localName){
return new LiveNodeList(this,function(base){
var ls = [];
_visitNode(base,function(node){
if(node !== base && node.nodeType === ELEMENT_NODE && node.namespaceURI === namespaceURI && (localName === '*' || node.localName == localName)){
ls.push(node);
}
});
return ls;
});
}
};
Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
_extends(Element,Node);
function Attr() {
};
Attr.prototype.nodeType = ATTRIBUTE_NODE;
_extends(Attr,Node);
function CharacterData() {
};
CharacterData.prototype = {
data : '',
substringData : function(offset, count) {
return this.data.substring(offset, offset+count);
},
appendData: function(text) {
text = this.data+text;
this.nodeValue = this.data = text;
this.length = text.length;
},
insertData: function(offset,text) {
this.replaceData(offset,0,text);
},
appendChild:function(newChild){
//if(!(newChild instanceof CharacterData)){
throw new Error(ExceptionMessage[3])
//}
return Node.prototype.appendChild.apply(this,arguments)
},
deleteData: function(offset, count) {
this.replaceData(offset,count,"");
},
replaceData: function(offset, count, text) {
var start = this.data.substring(0,offset);
var end = this.data.substring(offset+count);
text = start + text + end;
this.nodeValue = this.data = text;
this.length = text.length;
}
}
_extends(CharacterData,Node);
function Text() {
};
Text.prototype = {
nodeName : "#text",
nodeType : TEXT_NODE,
splitText : function(offset) {
var text = this.data;
var newText = text.substring(offset);
text = text.substring(0, offset);
this.data = this.nodeValue = text;
this.length = text.length;
var newNode = this.ownerDocument.createTextNode(newText);
if(this.parentNode){
this.parentNode.insertBefore(newNode, this.nextSibling);
}
return newNode;
}
}
_extends(Text,CharacterData);
function Comment() {
};
Comment.prototype = {
nodeName : "#comment",
nodeType : COMMENT_NODE
}
_extends(Comment,CharacterData);
function CDATASection() {
};
CDATASection.prototype = {
nodeName : "#cdata-section",
nodeType : CDATA_SECTION_NODE
}
_extends(CDATASection,CharacterData);
function DocumentType() {
};
DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
_extends(DocumentType,Node);
function Notation() {
};
Notation.prototype.nodeType = NOTATION_NODE;
_extends(Notation,Node);
function Entity() {
};
Entity.prototype.nodeType = ENTITY_NODE;
_extends(Entity,Node);
function EntityReference() {
};
EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
_extends(EntityReference,Node);
function DocumentFragment() {
};
DocumentFragment.prototype.nodeName = "#document-fragment";
DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
_extends(DocumentFragment,Node);
function ProcessingInstruction() {
}
ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
_extends(ProcessingInstruction,Node);
function XMLSerializer(){}
XMLSerializer.prototype.serializeToString = function(node){
var buf = [];
serializeToString(node,buf);
return buf.join('');
}
Node.prototype.toString =function(){
return XMLSerializer.prototype.serializeToString(this);
}
function serializeToString(node,buf){
switch(node.nodeType){
case ELEMENT_NODE:
var attrs = node.attributes;
var len = attrs.length;
var child = node.firstChild;
var nodeName = node.tagName;
var isHTML = htmlns === node.namespaceURI
buf.push('<',nodeName);
for(var i=0;i<len;i++){
serializeToString(attrs.item(i),buf,isHTML);
}
if(child || isHTML && !/^(?:meta|link|img|br|hr|input)$/i.test(nodeName)){
buf.push('>');
//if is cdata child node
if(isHTML && /^script$/i.test(nodeName)){
if(child){
buf.push(child.data);
}
}else{
while(child){
serializeToString(child,buf);
child = child.nextSibling;
}
}
buf.push('</',nodeName,'>');
}else{
buf.push('/>');
}
return;
case DOCUMENT_NODE:
case DOCUMENT_FRAGMENT_NODE:
var child = node.firstChild;
while(child){
serializeToString(child,buf);
child = child.nextSibling;
}
return;
case ATTRIBUTE_NODE:
return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
case TEXT_NODE:
return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
case CDATA_SECTION_NODE:
return buf.push( '<![CDATA[',node.data,']]>');
case COMMENT_NODE:
return buf.push( "<!--",node.data,"-->");
case DOCUMENT_TYPE_NODE:
var pubid = node.publicId;
var sysid = node.systemId;
buf.push('<!DOCTYPE ',node.name);
if(pubid){
buf.push(' PUBLIC "',pubid);
if (sysid && sysid!='.') {
buf.push( '" "',sysid);
}
buf.push('">');
}else if(sysid && sysid!='.'){
buf.push(' SYSTEM "',sysid,'">');
}else{
var sub = node.internalSubset;
if(sub){
buf.push(" [",sub,"]");
}
buf.push(">");
}
return;
case PROCESSING_INSTRUCTION_NODE:
return buf.push( "<?",node.target," ",node.data,"?>");
case ENTITY_REFERENCE_NODE:
return buf.push( '&',node.nodeName,';');
//case ENTITY_NODE:
//case NOTATION_NODE:
default:
buf.push('??',node.nodeName);
}
}
function importNode(doc,node,deep){
var node2;
switch (node.nodeType) {
case ELEMENT_NODE:
node2 = node.cloneNode(false);
node2.ownerDocument = doc;
//var attrs = node2.attributes;
//var len = attrs.length;
//for(var i=0;i<len;i++){
//node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
//}
case DOCUMENT_FRAGMENT_NODE:
break;
case ATTRIBUTE_NODE:
deep = true;
break;
//case ENTITY_REFERENCE_NODE:
//case PROCESSING_INSTRUCTION_NODE:
////case TEXT_NODE:
//case CDATA_SECTION_NODE:
//case COMMENT_NODE:
// deep = false;
// break;
//case DOCUMENT_NODE:
//case DOCUMENT_TYPE_NODE:
//cannot be imported.
//case ENTITY_NODE:
//case NOTATION_NODE:
//can not hit in level3
//default:throw e;
}
if(!node2){
node2 = node.cloneNode(false);//false
}
node2.ownerDocument = doc;
node2.parentNode = null;
if(deep){
var child = node.firstChild;
while(child){
node2.appendChild(importNode(doc,child,deep));
child = child.nextSibling;
}
}
return node2;
}
//
//var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
// attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
function cloneNode(doc,node,deep){
var node2 = new node.constructor();
for(var n in node){
var v = node[n];
if(typeof v != 'object' ){
if(v != node2[n]){
node2[n] = v;
}
}
}
if(node.childNodes){
node2.childNodes = new NodeList();
}
node2.ownerDocument = doc;
switch (node2.nodeType) {
case ELEMENT_NODE:
var attrs = node.attributes;
var attrs2 = node2.attributes = new NamedNodeMap();
var len = attrs.length
attrs2._ownerElement = node2;
for(var i=0;i<len;i++){
node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
}
break;;
case ATTRIBUTE_NODE:
deep = true;
}
if(deep){
var child = node.firstChild;
while(child){
node2.appendChild(cloneNode(doc,child,deep));
child = child.nextSibling;
}
}
return node2;
}
function __set__(object,key,value){
object[key] = value
}
//do dynamic
try{
Eif(Object.defineProperty){
Object.defineProperty(LiveNodeList.prototype,'length',{
get:function(){
_updateLiveList(this);
return this.$$length;
}
});
Object.defineProperty(Node.prototype,'textContent',{
get:function(){
return getTextContent(this);
},
set:function(data){
switch(this.nodeType){
case 1:
case 11:
while(this.firstChild){
this.removeChild(this.firstChild);
}
if(data || String(data)){
this.appendChild(this.ownerDocument.createTextNode(data));
}
break;
default:
//TODO:
this.data = data;
this.value = value;
this.nodeValue = data;
}
}
})
function getTextContent(node){
switch(node.nodeType){
case 1:
case 11:
var buf = [];
node = node.firstChild;
while(node){
if(node.nodeType!==7 && node.nodeType !==8){
buf.push(getTextContent(node));
}
node = node.nextSibling;
}
return buf.join('');
default:
return node.nodeValue;
}
}
__set__ = function(object,key,value){
//console.log(value)
object['$$'+key] = value
}
}
}catch(e){//ie8
}
Eif(typeof require == 'function'){
exports.DOMImplementation = DOMImplementation;
exports.XMLSerializer = XMLSerializer;
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | //[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
//[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
//[5] Name ::= NameStartChar (NameChar)*
var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\ux203F-\u2040]");
var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
//var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
//var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
//S_TAG, S_ATTR, S_EQ, S_V
//S_ATTR_S, S_E, S_S, S_C
var S_TAG = 0;//tag name offerring
var S_ATTR = 1;//attr name offerring
var S_ATTR_S=2;//attr name end and space offer
var S_EQ = 3;//=space?
var S_V = 4;//attr value(no quot value only)
var S_E = 5;//attr value end and no space(quot end)
var S_S = 6;//(attr value end || tag end ) && (space offer)
var S_C = 7;//closed el<el />
function XMLReader(){
}
XMLReader.prototype = {
parse:function(source,defaultNSMap,entityMap){
var domBuilder = this.domBuilder;
domBuilder.startDocument();
_copy(defaultNSMap ,defaultNSMap = {})
parse(source,defaultNSMap,entityMap,
domBuilder,this.errorHandler);
domBuilder.endDocument();
}
}
function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
function fixedFromCharCode(code) {
// String.prototype.fromCharCode does not supports
// > 2 bytes unicode chars directly
if (code > 0xffff) {
code -= 0x10000;
var surrogate1 = 0xd800 + (code >> 10)
, surrogate2 = 0xdc00 + (code & 0x3ff);
return String.fromCharCode(surrogate1, surrogate2);
} else {
return String.fromCharCode(code);
}
}
function entityReplacer(a){
var k = a.slice(1,-1);
if(k in entityMap){
return entityMap[k];
}else if(k.charAt(0) === '#'){
return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
}else{
errorHandler.error('entity not found:'+a);
return a;
}
}
function appendText(end){//has some bugs
var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
locator&&position(start);
domBuilder.characters(xt,0,end-start);
start = end
}
function position(start,m){
while(start>=endPos && (m = linePattern.exec(source))){
startPos = m.index;
endPos = startPos + m[0].length;
locator.lineNumber++;
//console.log('line++:',locator,startPos,endPos)
}
locator.columnNumber = start-startPos+1;
}
var startPos = 0;
var endPos = 0;
var linePattern = /.+(?:\r\n?|\n)|.*$/g
var locator = domBuilder.locator;
var parseStack = [{currentNSMap:defaultNSMapCopy}]
var closeMap = {};
var start = 0;
while(true){
var i = source.indexOf('<',start);
if(i<0){
if(!source.substr(start).match(/^\s*$/)){
var doc = domBuilder.document;
var text = doc.createTextNode(source.substr(start));
doc.appendChild(text);
domBuilder.currentElement = text;
}
return;
}
if(i>start){
appendText(i);
}
switch(source.charAt(i+1)){
case '/':
var end = source.indexOf('>',i+3);
var tagName = source.substring(i+2,end);
var config = parseStack.pop();
var localNSMap = config.localNSMap;
if(config.tagName != tagName){
errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
}
domBuilder.endElement(config.uri,config.localName,tagName);
if(localNSMap){
for(var prefix in localNSMap){
domBuilder.endPrefixMapping(prefix) ;
}
}
end++;
break;
// end elment
case '?':// <?...?>
locator&&position(i);
end = parseInstruction(source,i,domBuilder);
break;
case '!':// <!doctype,<![CDATA,<!--
locator&&position(i);
end = parseDCC(source,i,domBuilder,errorHandler);
break;
default:
try{
locator&&position(i);
var el = new ElementAttributes();
//elStartEnd
var end = parseElementStartPart(source,i,el,entityReplacer,errorHandler);
var len = el.length;
//position fixed
if(len && locator){
var backup = copyLocator(locator,{});
for(var i = 0;i<len;i++){
var a = el[i];
position(a.offset);
a.offset = copyLocator(locator,{});
}
copyLocator(backup,locator);
}
if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
el.closed = true;
if(!entityMap.nbsp){
errorHandler.warning('unclosed xml attribute');
}
}
appendElement(el,domBuilder,parseStack);
if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder)
}else{
end++;
}
}catch(e){
errorHandler.error('element parse error: '+e);
end = -1;
}
}
if(end<0){
//TODO: 这里有可能sax回退,有位置错误风险
appendText(i+1);
}else{
start = end;
}
}
}
function copyLocator(f,t){
t.lineNumber = f.lineNumber;
t.columnNumber = f.columnNumber;
return t;
}
/**
* @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
* @return end of the elementStartPart(end of elementEndPart for selfClosed el)
*/
function parseElementStartPart(source,start,el,entityReplacer,errorHandler){
var attrName;
var value;
var p = ++start;
var s = S_TAG;//status
while(true){
var c = source.charAt(p);
switch(c){
case '=':
if(s === S_ATTR){//attrName
attrName = source.slice(start,p);
s = S_EQ;
}else if(s === S_ATTR_S){
s = S_EQ;
}else{
//fatalError: equal must after attrName or space after attrName
throw new Error('attribute equal must after attrName');
}
break;
case '\'':
case '"':
if(s === S_EQ){//equal
start = p+1;
p = source.indexOf(c,start)
if(p>0){
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
el.add(attrName,value,start-1);
s = S_E;
}else{
//fatalError: no end quot match
throw new Error('attribute value no end \''+c+'\' match');
}
}else if(s == S_V){
value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
//console.log(attrName,value,start,p)
el.add(attrName,value,start);
//console.dir(el)
errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
start = p+1;
s = S_E
}else{
//fatalError: no equal before
throw new Error('attribute value must after "="');
}
break;
case '/':
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));
case S_E:
case S_S:
case S_C:
s = S_C;
el.closed = true;
case S_V:
case S_ATTR:
case S_ATTR_S:
break;
//case S_EQ:
default:
throw new Error("attribute invalid close char('/')")
}
break;
case ''://end document
//throw new Error('unexpected end of input')
errorHandler.error('unexpected end of input');
case '>':
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));
case S_E:
case S_S:
case S_C:
break;//normal
case S_V://Compatible state
case S_ATTR:
value = source.slice(start,p);
if(value.slice(-1) === '/'){
el.closed = true;
value = value.slice(0,-1)
}
case S_ATTR_S:
if(s === S_ATTR_S){
value = attrName;
}
if(s == S_V){
errorHandler.warning('attribute "'+value+'" missed quot(")!!');
el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start)
}else{
errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
el.add(value,value,start)
}
break;
case S_EQ:
throw new Error('attribute value missed!!');
}
// console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
return p;
/*xml space '\x20' | #x9 | #xD | #xA; */
case '\u0080':
c = ' ';
default:
if(c<= ' '){//space
switch(s){
case S_TAG:
el.setTagName(source.slice(start,p));//tagName
s = S_S;
break;
case S_ATTR:
attrName = source.slice(start,p)
s = S_ATTR_S;
break;
case S_V:
var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
errorHandler.warning('attribute "'+value+'" missed quot(")!!');
el.add(attrName,value,start)
case S_E:
s = S_S;
break;
//case S_S:
//case S_EQ:
//case S_ATTR_S:
// void();break;
//case S_C:
//ignore warning
}
}else{//not space
//S_TAG, S_ATTR, S_EQ, S_V
//S_ATTR_S, S_E, S_S, S_C
switch(s){
//case S_TAG:void();break;
//case S_ATTR:void();break;
//case S_V:void();break;
case S_ATTR_S:
errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!')
el.add(attrName,attrName,start);
start = p;
s = S_ATTR;
break;
case S_E:
errorHandler.warning('attribute space is required"'+attrName+'"!!')
case S_S:
s = S_ATTR;
start = p;
break;
case S_EQ:
s = S_V;
start = p;
break;
case S_C:
throw new Error("elements closed character '/' and '>' must be connected to");
}
}
}
p++;
}
}
/**
* @return end of the elementStartPart(end of elementEndPart for selfClosed el)
*/
function appendElement(el,domBuilder,parseStack){
var tagName = el.tagName;
var localNSMap = null;
var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
var i = el.length;
while(i--){
var a = el[i];
var qName = a.qName;
var value = a.value;
var nsp = qName.indexOf(':');
if(nsp>0){
var prefix = a.prefix = qName.slice(0,nsp);
var localName = qName.slice(nsp+1);
var nsPrefix = prefix === 'xmlns' && localName
}else{
localName = qName;
prefix = null
nsPrefix = qName === 'xmlns' && ''
}
//can not set prefix,because prefix !== ''
a.localName = localName ;
//prefix == null for no ns prefix attribute
if(nsPrefix !== false){//hack!!
if(localNSMap == null){
localNSMap = {}
//console.log(currentNSMap,0)
_copy(currentNSMap,currentNSMap={})
//console.log(currentNSMap,1)
}
currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
a.uri = 'http://www.w3.org/2000/xmlns/'
domBuilder.startPrefixMapping(nsPrefix, value)
}
}
var i = el.length;
while(i--){
a = el[i];
var prefix = a.prefix;
if(prefix){//no prefix attribute has no namespace
if(prefix === 'xml'){
a.uri = 'http://www.w3.org/XML/1998/namespace';
}if(prefix !== 'xmlns'){
a.uri = currentNSMap[prefix]
//{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
}
}
}
var nsp = tagName.indexOf(':');
if(nsp>0){
prefix = el.prefix = tagName.slice(0,nsp);
localName = el.localName = tagName.slice(nsp+1);
}else{
prefix = null;//important!!
localName = el.localName = tagName;
}
//no prefix element has default namespace
var ns = el.uri = currentNSMap[prefix || ''];
domBuilder.startElement(ns,localName,tagName,el);
//endPrefixMapping and startPrefixMapping have not any help for dom builder
//localNSMap = null
if(el.closed){
domBuilder.endElement(ns,localName,tagName);
if(localNSMap){
for(prefix in localNSMap){
domBuilder.endPrefixMapping(prefix)
}
}
}else{
el.currentNSMap = currentNSMap;
el.localNSMap = localNSMap;
parseStack.push(el);
}
}
function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
if(/^(?:script|textarea)$/i.test(tagName)){
var elEndStart = source.indexOf('</'+tagName+'>',elStartEnd);
var text = source.substring(elStartEnd+1,elEndStart);
if(/[&<]/.test(text)){
if(/^script$/i.test(tagName)){
//if(!/\]\]>/.test(text)){
//lexHandler.startCDATA();
domBuilder.characters(text,0,text.length);
//lexHandler.endCDATA();
return elEndStart;
//}
}//}else{//text area
text = text.replace(/&#?\w+;/g,entityReplacer);
domBuilder.characters(text,0,text.length);
return elEndStart;
//}
}
}
return elStartEnd+1;
}
function fixSelfClosed(source,elStartEnd,tagName,closeMap){
//if(tagName in closeMap){
var pos = closeMap[tagName];
if(pos == null){
//console.log(tagName)
pos = closeMap[tagName] = source.lastIndexOf('</'+tagName+'>')
}
return pos<elStartEnd;
//}
}
function _copy(source,target){
for(var n in source){target[n] = source[n]}
}
function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
var next= source.charAt(start+2)
switch(next){
case '-':
if(source.charAt(start + 3) === '-'){
var end = source.indexOf('-->',start+4);
//append comment source.substring(4,end)//<!--
if(end>start){
domBuilder.comment(source,start+4,end-start-4);
return end+3;
}else{
errorHandler.error("Unclosed comment");
return -1;
}
}else{
//error
return -1;
}
default:
if(source.substr(start+3,6) == 'CDATA['){
var end = source.indexOf(']]>',start+9);
domBuilder.startCDATA();
domBuilder.characters(source,start+9,end-start-9);
domBuilder.endCDATA()
return end+3;
}
//<!DOCTYPE
//startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
var matchs = split(source,start);
var len = matchs.length;
if(len>1 && /!doctype/i.test(matchs[0][0])){
var name = matchs[1][0];
var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0]
var sysid = len>4 && matchs[4][0];
var lastMatch = matchs[len-1]
domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
domBuilder.endDTD();
return lastMatch.index+lastMatch[0].length
}
}
return -1;
}
function parseInstruction(source,start,domBuilder){
var end = source.indexOf('?>',start);
if(end){
var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
if(match){
var len = match[0].length;
domBuilder.processingInstruction(match[1], match[2]) ;
return end+2;
}else{//error
return -1;
}
}
return -1;
}
/**
* @param source
*/
function ElementAttributes(source){
}
ElementAttributes.prototype = {
setTagName:function(tagName){
if(!tagNamePattern.test(tagName)){
throw new Error('invalid tagName:'+tagName)
}
this.tagName = tagName
},
add:function(qName,value,offset){
if(!tagNamePattern.test(qName)){
throw new Error('invalid attribute:'+qName)
}
this[this.length++] = {qName:qName,value:value,offset:offset}
},
length:0,
getLocalName:function(i){return this[i].localName},
getOffset:function(i){return this[i].offset},
getQName:function(i){return this[i].qName},
getURI:function(i){return this[i].uri},
getValue:function(i){return this[i].value}
// ,getIndex:function(uri, localName)){
// if(localName){
//
// }else{
// var qName = uri
// }
// },
// getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
// getType:function(uri,localName){}
// getType:function(i){},
}
function _set_proto_(thiz,parent){
thiz.__proto__ = parent;
return thiz;
}
Iif(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
_set_proto_ = function(thiz,parent){
function p(){};
p.prototype = parent;
p = new p();
for(parent in thiz){
p[parent] = thiz[parent];
}
return p;
}
}
function split(source,start){
var match;
var buf = [];
var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
reg.lastIndex = start;
reg.exec(source);//skip <
while(match = reg.exec(source)){
buf.push(match);
if(match[1])return buf;
}
}
Eif(typeof require == 'function'){
exports.XMLReader = XMLReader;
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| semver.js | 27.44% | (183 / 667) | 1.94% | (7 / 360) | 1.23% | (1 / 81) | 27.85% | (183 / 657) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 34 34 31 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | exports = module.exports = SemVer; // The debug function is excluded entirely from the minified version. /* nomin */ var debug; /* nomin */ Iif (typeof process === 'object' && /* nomin */ process.env && /* nomin */ process.env.NODE_DEBUG && /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) /* nomin */ debug = function() { /* nomin */ var args = Array.prototype.slice.call(arguments, 0); /* nomin */ args.unshift('SEMVER'); /* nomin */ console.log.apply(console, args); /* nomin */ }; /* nomin */ else /* nomin */ debug = function() {}; // Note: this is the semver.org version of the spec that it implements // Not necessarily the package version of this code. exports.SEMVER_SPEC_VERSION = '2.0.0'; var MAX_LENGTH = 256; var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; // The actual regexps go on exports.re var re = exports.re = []; var src = exports.src = []; var R = 0; // The following Regular Expressions can be used for tokenizing, // validating, and parsing SemVer version strings. // ## Numeric Identifier // A single `0`, or a non-zero digit followed by zero or more digits. var NUMERICIDENTIFIER = R++; src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; var NUMERICIDENTIFIERLOOSE = R++; src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; // ## Non-numeric Identifier // Zero or more digits, followed by a letter or hyphen, and then zero or // more letters, digits, or hyphens. var NONNUMERICIDENTIFIER = R++; src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; // ## Main Version // Three dot-separated numeric identifiers. var MAINVERSION = R++; src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + '(' + src[NUMERICIDENTIFIER] + ')\\.' + '(' + src[NUMERICIDENTIFIER] + ')'; var MAINVERSIONLOOSE = R++; src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; // ## Pre-release Version Identifier // A numeric identifier, or a non-numeric identifier. var PRERELEASEIDENTIFIER = R++; src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + '|' + src[NONNUMERICIDENTIFIER] + ')'; var PRERELEASEIDENTIFIERLOOSE = R++; src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + '|' + src[NONNUMERICIDENTIFIER] + ')'; // ## Pre-release Version // Hyphen, followed by one or more dot-separated pre-release version // identifiers. var PRERELEASE = R++; src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; var PRERELEASELOOSE = R++; src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; // ## Build Metadata Identifier // Any combination of digits, letters, or hyphens. var BUILDIDENTIFIER = R++; src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; // ## Build Metadata // Plus sign, followed by one or more period-separated build metadata // identifiers. var BUILD = R++; src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; // ## Full Version String // A main version, followed optionally by a pre-release version and // build metadata. // Note that the only major, minor, patch, and pre-release sections of // the version string are capturing groups. The build metadata is not a // capturing group, because it should not ever be used in version // comparison. var FULL = R++; var FULLPLAIN = 'v?' + src[MAINVERSION] + src[PRERELEASE] + '?' + src[BUILD] + '?'; src[FULL] = '^' + FULLPLAIN + '$'; // like full, but allows v1.2.3 and =1.2.3, which people do sometimes. // also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty // common in the npm registry. var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + src[PRERELEASELOOSE] + '?' + src[BUILD] + '?'; var LOOSE = R++; src[LOOSE] = '^' + LOOSEPLAIN + '$'; var GTLT = R++; src[GTLT] = '((?:<|>)?=?)'; // Something like "2.*" or "1.2.x". // Note that "x.x" is a valid xRange identifer, meaning "any version" // Only the first item is strictly required. var XRANGEIDENTIFIERLOOSE = R++; src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; var XRANGEIDENTIFIER = R++; src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; var XRANGEPLAIN = R++; src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + '(?:' + src[PRERELEASE] + ')?' + src[BUILD] + '?' + ')?)?'; var XRANGEPLAINLOOSE = R++; src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + '(?:' + src[PRERELEASELOOSE] + ')?' + src[BUILD] + '?' + ')?)?'; var XRANGE = R++; src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; var XRANGELOOSE = R++; src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; // Tilde ranges. // Meaning is "reasonably at or greater than" var LONETILDE = R++; src[LONETILDE] = '(?:~>?)'; var TILDETRIM = R++; src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); var tildeTrimReplace = '$1~'; var TILDE = R++; src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; var TILDELOOSE = R++; src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; // Caret ranges. // Meaning is "at least and backwards compatible with" var LONECARET = R++; src[LONECARET] = '(?:\\^)'; var CARETTRIM = R++; src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); var caretTrimReplace = '$1^'; var CARET = R++; src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; var CARETLOOSE = R++; src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; // A simple gt/lt/eq thing, or just "" to indicate "any version" var COMPARATORLOOSE = R++; src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; var COMPARATOR = R++; src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; // An expression to strip any whitespace between the gtlt and the thing // it modifies, so that `> 1.2.3` ==> `>1.2.3` var COMPARATORTRIM = R++; src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; // this one has to use the /g flag re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); var comparatorTrimReplace = '$1$2$3'; // Something like `1.2.3 - 1.2.4` // Note that these all use the loose form, because they'll be // checked against either the strict or loose comparator form // later. var HYPHENRANGE = R++; src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + '\\s+-\\s+' + '(' + src[XRANGEPLAIN] + ')' + '\\s*$'; var HYPHENRANGELOOSE = R++; src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + '\\s+-\\s+' + '(' + src[XRANGEPLAINLOOSE] + ')' + '\\s*$'; // Star ranges basically just allow anything at all. var STAR = R++; src[STAR] = '(<|>)?=?\\s*\\*'; // Compile to actual regexp objects. // All are flag-free, unless they were created above with a flag. for (var i = 0; i < R; i++) { debug(i, src[i]); if (!re[i]) re[i] = new RegExp(src[i]); } exports.parse = parse; function parse(version, loose) { if (version instanceof SemVer) return version; if (typeof version !== 'string') return null; if (version.length > MAX_LENGTH) return null; var r = loose ? re[LOOSE] : re[FULL]; if (!r.test(version)) return null; try { return new SemVer(version, loose); } catch (er) { return null; } } exports.valid = valid; function valid(version, loose) { var v = parse(version, loose); return v ? v.version : null; } exports.clean = clean; function clean(version, loose) { var s = parse(version.trim().replace(/^[=v]+/, ''), loose); return s ? s.version : null; } exports.SemVer = SemVer; function SemVer(version, loose) { if (version instanceof SemVer) { if (version.loose === loose) return version; else version = version.version; } else if (typeof version !== 'string') { throw new TypeError('Invalid Version: ' + version); } if (version.length > MAX_LENGTH) throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') if (!(this instanceof SemVer)) return new SemVer(version, loose); debug('SemVer', version, loose); this.loose = loose; var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); if (!m) throw new TypeError('Invalid Version: ' + version); this.raw = version; // these are actually numbers this.major = +m[1]; this.minor = +m[2]; this.patch = +m[3]; if (this.major > MAX_SAFE_INTEGER || this.major < 0) throw new TypeError('Invalid major version') if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) throw new TypeError('Invalid minor version') if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) throw new TypeError('Invalid patch version') // numberify any prerelease numeric ids if (!m[4]) this.prerelease = []; else this.prerelease = m[4].split('.').map(function(id) { if (/^[0-9]+$/.test(id)) { var num = +id if (num >= 0 && num < MAX_SAFE_INTEGER) return num } return id; }); this.build = m[5] ? m[5].split('.') : []; this.format(); } SemVer.prototype.format = function() { this.version = this.major + '.' + this.minor + '.' + this.patch; if (this.prerelease.length) this.version += '-' + this.prerelease.join('.'); return this.version; }; SemVer.prototype.inspect = function() { return '<SemVer "' + this + '">'; }; SemVer.prototype.toString = function() { return this.version; }; SemVer.prototype.compare = function(other) { debug('SemVer.compare', this.version, this.loose, other); if (!(other instanceof SemVer)) other = new SemVer(other, this.loose); return this.compareMain(other) || this.comparePre(other); }; SemVer.prototype.compareMain = function(other) { if (!(other instanceof SemVer)) other = new SemVer(other, this.loose); return compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch); }; SemVer.prototype.comparePre = function(other) { if (!(other instanceof SemVer)) other = new SemVer(other, this.loose); // NOT having a prerelease is > having one if (this.prerelease.length && !other.prerelease.length) return -1; else if (!this.prerelease.length && other.prerelease.length) return 1; else if (!this.prerelease.length && !other.prerelease.length) return 0; var i = 0; do { var a = this.prerelease[i]; var b = other.prerelease[i]; debug('prerelease compare', i, a, b); if (a === undefined && b === undefined) return 0; else if (b === undefined) return 1; else if (a === undefined) return -1; else if (a === b) continue; else return compareIdentifiers(a, b); } while (++i); }; // preminor will bump the version up to the next minor release, and immediately // down to pre-release. premajor and prepatch work the same way. SemVer.prototype.inc = function(release, identifier) { switch (release) { case 'premajor': this.prerelease.length = 0; this.patch = 0; this.minor = 0; this.major++; this.inc('pre', identifier); break; case 'preminor': this.prerelease.length = 0; this.patch = 0; this.minor++; this.inc('pre', identifier); break; case 'prepatch': // If this is already a prerelease, it will bump to the next version // drop any prereleases that might already exist, since they are not // relevant at this point. this.prerelease.length = 0; this.inc('patch', identifier); this.inc('pre', identifier); break; // If the input is a non-prerelease version, this acts the same as // prepatch. case 'prerelease': if (this.prerelease.length === 0) this.inc('patch', identifier); this.inc('pre', identifier); break; case 'major': // If this is a pre-major version, bump up to the same major version. // Otherwise increment major. // 1.0.0-5 bumps to 1.0.0 // 1.1.0 bumps to 2.0.0 if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) this.major++; this.minor = 0; this.patch = 0; this.prerelease = []; break; case 'minor': // If this is a pre-minor version, bump up to the same minor version. // Otherwise increment minor. // 1.2.0-5 bumps to 1.2.0 // 1.2.1 bumps to 1.3.0 if (this.patch !== 0 || this.prerelease.length === 0) this.minor++; this.patch = 0; this.prerelease = []; break; case 'patch': // If this is not a pre-release version, it will increment the patch. // If it is a pre-release it will bump up to the same patch version. // 1.2.0-5 patches to 1.2.0 // 1.2.0 patches to 1.2.1 if (this.prerelease.length === 0) this.patch++; this.prerelease = []; break; // This probably shouldn't be used publicly. // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. case 'pre': if (this.prerelease.length === 0) this.prerelease = [0]; else { var i = this.prerelease.length; while (--i >= 0) { if (typeof this.prerelease[i] === 'number') { this.prerelease[i]++; i = -2; } } if (i === -1) // didn't increment anything this.prerelease.push(0); } if (identifier) { // 1.2.0-beta.1 bumps to 1.2.0-beta.2, // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 if (this.prerelease[0] === identifier) { if (isNaN(this.prerelease[1])) this.prerelease = [identifier, 0]; } else this.prerelease = [identifier, 0]; } break; default: throw new Error('invalid increment argument: ' + release); } this.format(); this.raw = this.version; return this; }; exports.inc = inc; function inc(version, release, loose, identifier) { if (typeof(loose) === 'string') { identifier = loose; loose = undefined; } try { return new SemVer(version, loose).inc(release, identifier).version; } catch (er) { return null; } } exports.diff = diff; function diff(version1, version2) { if (eq(version1, version2)) { return null; } else { var v1 = parse(version1); var v2 = parse(version2); if (v1.prerelease.length || v2.prerelease.length) { for (var key in v1) { if (key === 'major' || key === 'minor' || key === 'patch') { if (v1[key] !== v2[key]) { return 'pre'+key; } } } return 'prerelease'; } for (var key in v1) { if (key === 'major' || key === 'minor' || key === 'patch') { if (v1[key] !== v2[key]) { return key; } } } } } exports.compareIdentifiers = compareIdentifiers; var numeric = /^[0-9]+$/; function compareIdentifiers(a, b) { var anum = numeric.test(a); var bnum = numeric.test(b); if (anum && bnum) { a = +a; b = +b; } return (anum && !bnum) ? -1 : (bnum && !anum) ? 1 : a < b ? -1 : a > b ? 1 : 0; } exports.rcompareIdentifiers = rcompareIdentifiers; function rcompareIdentifiers(a, b) { return compareIdentifiers(b, a); } exports.major = major; function major(a, loose) { return new SemVer(a, loose).major; } exports.minor = minor; function minor(a, loose) { return new SemVer(a, loose).minor; } exports.patch = patch; function patch(a, loose) { return new SemVer(a, loose).patch; } exports.compare = compare; function compare(a, b, loose) { return new SemVer(a, loose).compare(b); } exports.compareLoose = compareLoose; function compareLoose(a, b) { return compare(a, b, true); } exports.rcompare = rcompare; function rcompare(a, b, loose) { return compare(b, a, loose); } exports.sort = sort; function sort(list, loose) { return list.sort(function(a, b) { return exports.compare(a, b, loose); }); } exports.rsort = rsort; function rsort(list, loose) { return list.sort(function(a, b) { return exports.rcompare(a, b, loose); }); } exports.gt = gt; function gt(a, b, loose) { return compare(a, b, loose) > 0; } exports.lt = lt; function lt(a, b, loose) { return compare(a, b, loose) < 0; } exports.eq = eq; function eq(a, b, loose) { return compare(a, b, loose) === 0; } exports.neq = neq; function neq(a, b, loose) { return compare(a, b, loose) !== 0; } exports.gte = gte; function gte(a, b, loose) { return compare(a, b, loose) >= 0; } exports.lte = lte; function lte(a, b, loose) { return compare(a, b, loose) <= 0; } exports.cmp = cmp; function cmp(a, op, b, loose) { var ret; switch (op) { case '===': if (typeof a === 'object') a = a.version; if (typeof b === 'object') b = b.version; ret = a === b; break; case '!==': if (typeof a === 'object') a = a.version; if (typeof b === 'object') b = b.version; ret = a !== b; break; case '': case '=': case '==': ret = eq(a, b, loose); break; case '!=': ret = neq(a, b, loose); break; case '>': ret = gt(a, b, loose); break; case '>=': ret = gte(a, b, loose); break; case '<': ret = lt(a, b, loose); break; case '<=': ret = lte(a, b, loose); break; default: throw new TypeError('Invalid operator: ' + op); } return ret; } exports.Comparator = Comparator; function Comparator(comp, loose) { if (comp instanceof Comparator) { if (comp.loose === loose) return comp; else comp = comp.value; } if (!(this instanceof Comparator)) return new Comparator(comp, loose); debug('comparator', comp, loose); this.loose = loose; this.parse(comp); if (this.semver === ANY) this.value = ''; else this.value = this.operator + this.semver.version; debug('comp', this); } var ANY = {}; Comparator.prototype.parse = function(comp) { var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; var m = comp.match(r); if (!m) throw new TypeError('Invalid comparator: ' + comp); this.operator = m[1]; if (this.operator === '=') this.operator = ''; // if it literally is just '>' or '' then allow anything. if (!m[2]) this.semver = ANY; else this.semver = new SemVer(m[2], this.loose); }; Comparator.prototype.inspect = function() { return '<SemVer Comparator "' + this + '">'; }; Comparator.prototype.toString = function() { return this.value; }; Comparator.prototype.test = function(version) { debug('Comparator.test', version, this.loose); if (this.semver === ANY) return true; if (typeof version === 'string') version = new SemVer(version, this.loose); return cmp(version, this.operator, this.semver, this.loose); }; exports.Range = Range; function Range(range, loose) { if ((range instanceof Range) && range.loose === loose) return range; if (!(this instanceof Range)) return new Range(range, loose); this.loose = loose; // First, split based on boolean or || this.raw = range; this.set = range.split(/\s*\|\|\s*/).map(function(range) { return this.parseRange(range.trim()); }, this).filter(function(c) { // throw out any that are not relevant for whatever reason return c.length; }); if (!this.set.length) { throw new TypeError('Invalid SemVer Range: ' + range); } this.format(); } Range.prototype.inspect = function() { return '<SemVer Range "' + this.range + '">'; }; Range.prototype.format = function() { this.range = this.set.map(function(comps) { return comps.join(' ').trim(); }).join('||').trim(); return this.range; }; Range.prototype.toString = function() { return this.range; }; Range.prototype.parseRange = function(range) { var loose = this.loose; range = range.trim(); debug('range', range, loose); // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; range = range.replace(hr, hyphenReplace); debug('hyphen replace', range); // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); debug('comparator trim', range, re[COMPARATORTRIM]); // `~ 1.2.3` => `~1.2.3` range = range.replace(re[TILDETRIM], tildeTrimReplace); // `^ 1.2.3` => `^1.2.3` range = range.replace(re[CARETTRIM], caretTrimReplace); // normalize spaces range = range.split(/\s+/).join(' '); // At this point, the range is completely trimmed and // ready to be split into comparators. var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; var set = range.split(' ').map(function(comp) { return parseComparator(comp, loose); }).join(' ').split(/\s+/); if (this.loose) { // in loose mode, throw out any that are not valid comparators set = set.filter(function(comp) { return !!comp.match(compRe); }); } set = set.map(function(comp) { return new Comparator(comp, loose); }); return set; }; // Mostly just for testing and legacy API reasons exports.toComparators = toComparators; function toComparators(range, loose) { return new Range(range, loose).set.map(function(comp) { return comp.map(function(c) { return c.value; }).join(' ').trim().split(' '); }); } // comprised of xranges, tildes, stars, and gtlt's at this point. // already replaced the hyphen ranges // turn into a set of JUST comparators. function parseComparator(comp, loose) { debug('comp', comp); comp = replaceCarets(comp, loose); debug('caret', comp); comp = replaceTildes(comp, loose); debug('tildes', comp); comp = replaceXRanges(comp, loose); debug('xrange', comp); comp = replaceStars(comp, loose); debug('stars', comp); return comp; } function isX(id) { return !id || id.toLowerCase() === 'x' || id === '*'; } // ~, ~> --> * (any, kinda silly) // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 // ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 // ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 function replaceTildes(comp, loose) { return comp.trim().split(/\s+/).map(function(comp) { return replaceTilde(comp, loose); }).join(' '); } function replaceTilde(comp, loose) { var r = loose ? re[TILDELOOSE] : re[TILDE]; return comp.replace(r, function(_, M, m, p, pr) { debug('tilde', comp, _, M, m, p, pr); var ret; if (isX(M)) ret = ''; else if (isX(m)) ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; else if (isX(p)) // ~1.2 == >=1.2.0- <1.3.0- ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; else if (pr) { debug('replaceTilde pr', pr); if (pr.charAt(0) !== '-') pr = '-' + pr; ret = '>=' + M + '.' + m + '.' + p + pr + ' <' + M + '.' + (+m + 1) + '.0'; } else // ~1.2.3 == >=1.2.3 <1.3.0 ret = '>=' + M + '.' + m + '.' + p + ' <' + M + '.' + (+m + 1) + '.0'; debug('tilde return', ret); return ret; }); } // ^ --> * (any, kinda silly) // ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 // ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 // ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 // ^1.2.3 --> >=1.2.3 <2.0.0 // ^1.2.0 --> >=1.2.0 <2.0.0 function replaceCarets(comp, loose) { return comp.trim().split(/\s+/).map(function(comp) { return replaceCaret(comp, loose); }).join(' '); } function replaceCaret(comp, loose) { debug('caret', comp, loose); var r = loose ? re[CARETLOOSE] : re[CARET]; return comp.replace(r, function(_, M, m, p, pr) { debug('caret', comp, _, M, m, p, pr); var ret; if (isX(M)) ret = ''; else if (isX(m)) ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; else if (isX(p)) { if (M === '0') ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; else ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; } else if (pr) { debug('replaceCaret pr', pr); if (pr.charAt(0) !== '-') pr = '-' + pr; if (M === '0') { if (m === '0') ret = '>=' + M + '.' + m + '.' + p + pr + ' <' + M + '.' + m + '.' + (+p + 1); else ret = '>=' + M + '.' + m + '.' + p + pr + ' <' + M + '.' + (+m + 1) + '.0'; } else ret = '>=' + M + '.' + m + '.' + p + pr + ' <' + (+M + 1) + '.0.0'; } else { debug('no pr'); if (M === '0') { if (m === '0') ret = '>=' + M + '.' + m + '.' + p + ' <' + M + '.' + m + '.' + (+p + 1); else ret = '>=' + M + '.' + m + '.' + p + ' <' + M + '.' + (+m + 1) + '.0'; } else ret = '>=' + M + '.' + m + '.' + p + ' <' + (+M + 1) + '.0.0'; } debug('caret return', ret); return ret; }); } function replaceXRanges(comp, loose) { debug('replaceXRanges', comp, loose); return comp.split(/\s+/).map(function(comp) { return replaceXRange(comp, loose); }).join(' '); } function replaceXRange(comp, loose) { comp = comp.trim(); var r = loose ? re[XRANGELOOSE] : re[XRANGE]; return comp.replace(r, function(ret, gtlt, M, m, p, pr) { debug('xRange', comp, ret, gtlt, M, m, p, pr); var xM = isX(M); var xm = xM || isX(m); var xp = xm || isX(p); var anyX = xp; if (gtlt === '=' && anyX) gtlt = ''; if (xM) { if (gtlt === '>' || gtlt === '<') { // nothing is allowed ret = '<0.0.0'; } else { // nothing is forbidden ret = '*'; } } else if (gtlt && anyX) { // replace X with 0 if (xm) m = 0; if (xp) p = 0; if (gtlt === '>') { // >1 => >=2.0.0 // >1.2 => >=1.3.0 // >1.2.3 => >= 1.2.4 gtlt = '>='; if (xm) { M = +M + 1; m = 0; p = 0; } else if (xp) { m = +m + 1; p = 0; } } else if (gtlt === '<=') { // <=0.7.x is actually <0.8.0, since any 0.7.x should // pass. Similarly, <=7.x is actually <8.0.0, etc. gtlt = '<' if (xm) M = +M + 1 else m = +m + 1 } ret = gtlt + M + '.' + m + '.' + p; } else if (xm) { ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; } else if (xp) { ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; } debug('xRange return', ret); return ret; }); } // Because * is AND-ed with everything else in the comparator, // and '' means "any version", just remove the *s entirely. function replaceStars(comp, loose) { debug('replaceStars', comp, loose); // Looseness is ignored here. star is always as loose as it gets! return comp.trim().replace(re[STAR], ''); } // This function is passed to string.replace(re[HYPHENRANGE]) // M, m, patch, prerelease, build // 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 // 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do // 1.2 - 3.4 => >=1.2.0 <3.5.0 function hyphenReplace($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr, tb) { if (isX(fM)) from = ''; else if (isX(fm)) from = '>=' + fM + '.0.0'; else if (isX(fp)) from = '>=' + fM + '.' + fm + '.0'; else from = '>=' + from; if (isX(tM)) to = ''; else if (isX(tm)) to = '<' + (+tM + 1) + '.0.0'; else if (isX(tp)) to = '<' + tM + '.' + (+tm + 1) + '.0'; else if (tpr) to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; else to = '<=' + to; return (from + ' ' + to).trim(); } // if ANY of the sets match ALL of its comparators, then pass Range.prototype.test = function(version) { if (!version) return false; if (typeof version === 'string') version = new SemVer(version, this.loose); for (var i = 0; i < this.set.length; i++) { if (testSet(this.set[i], version)) return true; } return false; }; function testSet(set, version) { for (var i = 0; i < set.length; i++) { if (!set[i].test(version)) return false; } if (version.prerelease.length) { // Find the set of versions that are allowed to have prereleases // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 // That should allow `1.2.3-pr.2` to pass. // However, `1.2.4-alpha.notready` should NOT be allowed, // even though it's within the range set by the comparators. for (var i = 0; i < set.length; i++) { debug(set[i].semver); if (set[i].semver === ANY) continue; if (set[i].semver.prerelease.length > 0) { var allowed = set[i].semver; if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) return true; } } // Version has a -pre, but it's not one of the ones we like. return false; } return true; } exports.satisfies = satisfies; function satisfies(version, range, loose) { try { range = new Range(range, loose); } catch (er) { return false; } return range.test(version); } exports.maxSatisfying = maxSatisfying; function maxSatisfying(versions, range, loose) { return versions.filter(function(version) { return satisfies(version, range, loose); }).sort(function(a, b) { return rcompare(a, b, loose); })[0] || null; } exports.validRange = validRange; function validRange(range, loose) { try { // Return '*' instead of '' so that truthiness works. // This will throw if it's invalid anyway return new Range(range, loose).range || '*'; } catch (er) { return null; } } // Determine if version is less than all the versions possible in the range exports.ltr = ltr; function ltr(version, range, loose) { return outside(version, range, '<', loose); } // Determine if version is greater than all the versions possible in the range. exports.gtr = gtr; function gtr(version, range, loose) { return outside(version, range, '>', loose); } exports.outside = outside; function outside(version, range, hilo, loose) { version = new SemVer(version, loose); range = new Range(range, loose); var gtfn, ltefn, ltfn, comp, ecomp; switch (hilo) { case '>': gtfn = gt; ltefn = lte; ltfn = lt; comp = '>'; ecomp = '>='; break; case '<': gtfn = lt; ltefn = gte; ltfn = gt; comp = '<'; ecomp = '<='; break; default: throw new TypeError('Must provide a hilo val of "<" or ">"'); } // If it satisifes the range it is not outside if (satisfies(version, range, loose)) { return false; } // From now on, variable terms are as if we're in "gtr" mode. // but note that everything is flipped for the "ltr" function. for (var i = 0; i < range.set.length; ++i) { var comparators = range.set[i]; var high = null; var low = null; comparators.forEach(function(comparator) { if (comparator.semver === ANY) { comparator = new Comparator('>=0.0.0') } high = high || comparator; low = low || comparator; if (gtfn(comparator.semver, high.semver, loose)) { high = comparator; } else if (ltfn(comparator.semver, low.semver, loose)) { low = comparator; } }); // If the edge version comparator has a operator then our version // isn't outside it if (high.operator === comp || high.operator === ecomp) { return false; } // If the lowest version comparator has an operator and our version // is less than it then it isn't higher than the range if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) { return false; } else if (low.operator === ecomp && ltfn(version, low.semver)) { return false; } } return true; } |
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| underscore.js | 24.44% | (208 / 851) | 5.38% | (27 / 502) | 14.37% | (24 / 167) | 27.04% | (205 / 758) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 4 1 1 1 3 1 1 1 4 1 1 1 4 4 1 4 4 4 4 149 4 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 2 1 1 1 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 1 1 1 1 1 1 1 1 6 1 1 1 1 134 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 1 7 1 1 1 1 134 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 132 132 1 1 7 7 1 3 3 1 1 1 1 | // Underscore.js 1.8.3
// http://underscorejs.org
// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
// Underscore may be freely distributed under the MIT license.
(function() {
// Baseline setup
// --------------
// Establish the root object, `window` in the browser, or `exports` on the server.
var root = this;
// Save the previous value of the `_` variable.
var previousUnderscore = root._;
// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
// Create quick reference variables for speed access to core prototypes.
var
push = ArrayProto.push,
slice = ArrayProto.slice,
toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;
// All **ECMAScript 5** native function implementations that we hope to use
// are declared here.
var
nativeIsArray = Array.isArray,
nativeKeys = Object.keys,
nativeBind = FuncProto.bind,
nativeCreate = Object.create;
// Naked function reference for surrogate-prototype-swapping.
var Ctor = function(){};
// Create a safe reference to the Underscore object for use below.
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in
// the browser, add `_` as a global object.
Eif (typeof exports !== 'undefined') {
Eif (typeof module !== 'undefined' && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {
root._ = _;
}
// Current version.
_.VERSION = '1.8.3';
// Internal function that returns an efficient (for current engines) version
// of the passed-in callback, to be repeatedly applied in other Underscore
// functions.
var optimizeCb = function(func, context, argCount) {
Eif (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
case 2: return function(value, other) {
return func.call(context, value, other);
};
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
// A mostly-internal function to generate callbacks that can be applied
// to each element in a collection, returning the desired result — either
// identity, an arbitrary callback, a property matcher, or a property accessor.
var cb = function(value, context, argCount) {
if (value == null) return _.identity;
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
if (_.isObject(value)) return _.matcher(value);
return _.property(value);
};
_.iteratee = function(value, context) {
return cb(value, context, Infinity);
};
// An internal function for creating assigner functions.
var createAssigner = function(keysFunc, undefinedOnly) {
return function(obj) {
var length = arguments.length;
if (length < 2 || obj == null) return obj;
for (var index = 1; index < length; index++) {
var source = arguments[index],
keys = keysFunc(source),
l = keys.length;
for (var i = 0; i < l; i++) {
var key = keys[i];
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
}
}
return obj;
};
};
// An internal function for creating a new object that inherits from another.
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
var property = function(key) {
return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
// Helper for collection methods to determine whether a collection
// should be iterated as an array or as an object
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
var getLength = property('length');
var isArrayLike = function(collection) {
var length = getLength(collection);
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
};
// Collection Functions
// --------------------
// The cornerstone, an `each` implementation, aka `forEach`.
// Handles raw objects in addition to array-likes. Treats all
// sparse array-likes as if they were dense.
_.each = _.forEach = function(obj, iteratee, context) {
iteratee = optimizeCb(iteratee, context);
var i, length;
Eif (isArrayLike(obj)) {
for (i = 0, length = obj.length; i < length; i++) {
iteratee(obj[i], i, obj);
}
} else {
var keys = _.keys(obj);
for (i = 0, length = keys.length; i < length; i++) {
iteratee(obj[keys[i]], keys[i], obj);
}
}
return obj;
};
// Return the results of applying the iteratee to each element.
_.map = _.collect = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
results = Array(length);
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Create a reducing function iterating left or right.
function createReduce(dir) {
// Optimized iterator function as using arguments.length
// in the main function will deoptimize the, see #1991.
function iterator(obj, iteratee, memo, keys, index, length) {
for (; index >= 0 && index < length; index += dir) {
var currentKey = keys ? keys[index] : index;
memo = iteratee(memo, obj[currentKey], currentKey, obj);
}
return memo;
}
return function(obj, iteratee, memo, context) {
iteratee = optimizeCb(iteratee, context, 4);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
index = dir > 0 ? 0 : length - 1;
// Determine the initial value if none is provided.
if (arguments.length < 3) {
memo = obj[keys ? keys[index] : index];
index += dir;
}
return iterator(obj, iteratee, memo, keys, index, length);
};
}
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`.
_.reduce = _.foldl = _.inject = createReduce(1);
// The right-associative version of reduce, also known as `foldr`.
_.reduceRight = _.foldr = createReduce(-1);
// Return the first value which passes a truth test. Aliased as `detect`.
_.find = _.detect = function(obj, predicate, context) {
var key;
if (isArrayLike(obj)) {
key = _.findIndex(obj, predicate, context);
} else {
key = _.findKey(obj, predicate, context);
}
if (key !== void 0 && key !== -1) return obj[key];
};
// Return all the elements that pass a truth test.
// Aliased as `select`.
_.filter = _.select = function(obj, predicate, context) {
var results = [];
predicate = cb(predicate, context);
_.each(obj, function(value, index, list) {
if (predicate(value, index, list)) results.push(value);
});
return results;
};
// Return all the elements for which a truth test fails.
_.reject = function(obj, predicate, context) {
return _.filter(obj, _.negate(cb(predicate)), context);
};
// Determine whether all of the elements match a truth test.
// Aliased as `all`.
_.every = _.all = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length;
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
if (!predicate(obj[currentKey], currentKey, obj)) return false;
}
return true;
};
// Determine if at least one element in the object matches a truth test.
// Aliased as `any`.
_.some = _.any = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length;
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
if (predicate(obj[currentKey], currentKey, obj)) return true;
}
return false;
};
// Determine if the array or object contains a given item (using `===`).
// Aliased as `includes` and `include`.
_.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
if (!isArrayLike(obj)) obj = _.values(obj);
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
return _.indexOf(obj, item, fromIndex) >= 0;
};
// Invoke a method (with arguments) on every item in a collection.
_.invoke = function(obj, method) {
var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method);
return _.map(obj, function(value) {
var func = isFunc ? method : value[method];
return func == null ? func : func.apply(value, args);
});
};
// Convenience version of a common use case of `map`: fetching a property.
_.pluck = function(obj, key) {
return _.map(obj, _.property(key));
};
// Convenience version of a common use case of `filter`: selecting only objects
// containing specific `key:value` pairs.
_.where = function(obj, attrs) {
return _.filter(obj, _.matcher(attrs));
};
// Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) {
return _.find(obj, _.matcher(attrs));
};
// Return the maximum element (or element-based computation).
_.max = function(obj, iteratee, context) {
var result = -Infinity, lastComputed = -Infinity,
value, computed;
if (iteratee == null && obj != null) {
obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value > result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function(value, index, list) {
computed = iteratee(value, index, list);
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
result = value;
lastComputed = computed;
}
});
}
return result;
};
// Return the minimum element (or element-based computation).
_.min = function(obj, iteratee, context) {
var result = Infinity, lastComputed = Infinity,
value, computed;
if (iteratee == null && obj != null) {
obj = isArrayLike(obj) ? obj : _.values(obj);
for (var i = 0, length = obj.length; i < length; i++) {
value = obj[i];
if (value < result) {
result = value;
}
}
} else {
iteratee = cb(iteratee, context);
_.each(obj, function(value, index, list) {
computed = iteratee(value, index, list);
if (computed < lastComputed || computed === Infinity && result === Infinity) {
result = value;
lastComputed = computed;
}
});
}
return result;
};
// Shuffle a collection, using the modern version of the
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
_.shuffle = function(obj) {
var set = isArrayLike(obj) ? obj : _.values(obj);
var length = set.length;
var shuffled = Array(length);
for (var index = 0, rand; index < length; index++) {
rand = _.random(0, index);
if (rand !== index) shuffled[index] = shuffled[rand];
shuffled[rand] = set[index];
}
return shuffled;
};
// Sample **n** random values from a collection.
// If **n** is not specified, returns a single random element.
// The internal `guard` argument allows it to work with `map`.
_.sample = function(obj, n, guard) {
if (n == null || guard) {
if (!isArrayLike(obj)) obj = _.values(obj);
return obj[_.random(obj.length - 1)];
}
return _.shuffle(obj).slice(0, Math.max(0, n));
};
// Sort the object's values by a criterion produced by an iteratee.
_.sortBy = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
return _.pluck(_.map(obj, function(value, index, list) {
return {
value: value,
index: index,
criteria: iteratee(value, index, list)
};
}).sort(function(left, right) {
var a = left.criteria;
var b = right.criteria;
if (a !== b) {
if (a > b || a === void 0) return 1;
if (a < b || b === void 0) return -1;
}
return left.index - right.index;
}), 'value');
};
// An internal function used for aggregate "group by" operations.
var group = function(behavior) {
return function(obj, iteratee, context) {
var result = {};
iteratee = cb(iteratee, context);
_.each(obj, function(value, index) {
var key = iteratee(value, index, obj);
behavior(result, value, key);
});
return result;
};
};
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = group(function(result, value, key) {
if (_.has(result, key)) result[key].push(value); else result[key] = [value];
});
// Indexes the object's values by a criterion, similar to `groupBy`, but for
// when you know that your index values will be unique.
_.indexBy = group(function(result, value, key) {
result[key] = value;
});
// Counts instances of an object that group by a certain criterion. Pass
// either a string attribute to count by, or a function that returns the
// criterion.
_.countBy = group(function(result, value, key) {
if (_.has(result, key)) result[key]++; else result[key] = 1;
});
// Safely create a real, live array from anything iterable.
_.toArray = function(obj) {
if (!obj) return [];
if (_.isArray(obj)) return slice.call(obj);
if (isArrayLike(obj)) return _.map(obj, _.identity);
return _.values(obj);
};
// Return the number of elements in an object.
_.size = function(obj) {
if (obj == null) return 0;
return isArrayLike(obj) ? obj.length : _.keys(obj).length;
};
// Split a collection into two arrays: one whose elements all satisfy the given
// predicate, and one whose elements all do not satisfy the predicate.
_.partition = function(obj, predicate, context) {
predicate = cb(predicate, context);
var pass = [], fail = [];
_.each(obj, function(value, key, obj) {
(predicate(value, key, obj) ? pass : fail).push(value);
});
return [pass, fail];
};
// Array Functions
// ---------------
// Get the first element of an array. Passing **n** will return the first N
// values in the array. Aliased as `head` and `take`. The **guard** check
// allows it to work with `_.map`.
_.first = _.head = _.take = function(array, n, guard) {
if (array == null) return void 0;
if (n == null || guard) return array[0];
return _.initial(array, array.length - n);
};
// Returns everything but the last entry of the array. Especially useful on
// the arguments object. Passing **n** will return all the values in
// the array, excluding the last N.
_.initial = function(array, n, guard) {
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
};
// Get the last element of an array. Passing **n** will return the last N
// values in the array.
_.last = function(array, n, guard) {
if (array == null) return void 0;
if (n == null || guard) return array[array.length - 1];
return _.rest(array, Math.max(0, array.length - n));
};
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
// Especially useful on the arguments object. Passing an **n** will return
// the rest N values in the array.
_.rest = _.tail = _.drop = function(array, n, guard) {
return slice.call(array, n == null || guard ? 1 : n);
};
// Trim out all falsy values from an array.
_.compact = function(array) {
return _.filter(array, _.identity);
};
// Internal implementation of a recursive `flatten` function.
var flatten = function(input, shallow, strict, startIndex) {
var output = [], idx = 0;
for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
var value = input[i];
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
//flatten current level of array or arguments object
if (!shallow) value = flatten(value, shallow, strict);
var j = 0, len = value.length;
output.length += len;
while (j < len) {
output[idx++] = value[j++];
}
} else if (!strict) {
output[idx++] = value;
}
}
return output;
};
// Flatten out an array, either recursively (by default), or just one level.
_.flatten = function(array, shallow) {
return flatten(array, shallow, false);
};
// Return a version of the array that does not contain the specified value(s).
_.without = function(array) {
return _.difference(array, slice.call(arguments, 1));
};
// Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`.
_.uniq = _.unique = function(array, isSorted, iteratee, context) {
if (!_.isBoolean(isSorted)) {
context = iteratee;
iteratee = isSorted;
isSorted = false;
}
if (iteratee != null) iteratee = cb(iteratee, context);
var result = [];
var seen = [];
for (var i = 0, length = getLength(array); i < length; i++) {
var value = array[i],
computed = iteratee ? iteratee(value, i, array) : value;
if (isSorted) {
if (!i || seen !== computed) result.push(value);
seen = computed;
} else if (iteratee) {
if (!_.contains(seen, computed)) {
seen.push(computed);
result.push(value);
}
} else if (!_.contains(result, value)) {
result.push(value);
}
}
return result;
};
// Produce an array that contains the union: each distinct element from all of
// the passed-in arrays.
_.union = function() {
return _.uniq(flatten(arguments, true, true));
};
// Produce an array that contains every item shared between all the
// passed-in arrays.
_.intersection = function(array) {
var result = [];
var argsLength = arguments.length;
for (var i = 0, length = getLength(array); i < length; i++) {
var item = array[i];
if (_.contains(result, item)) continue;
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
};
// Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain.
_.difference = function(array) {
var rest = flatten(arguments, true, true, 1);
return _.filter(array, function(value){
return !_.contains(rest, value);
});
};
// Zip together multiple lists into a single array -- elements that share
// an index go together.
_.zip = function() {
return _.unzip(arguments);
};
// Complement of _.zip. Unzip accepts an array of arrays and groups
// each array's elements on shared indices
_.unzip = function(array) {
var length = array && _.max(array, getLength).length || 0;
var result = Array(length);
for (var index = 0; index < length; index++) {
result[index] = _.pluck(array, index);
}
return result;
};
// Converts lists into objects. Pass either a single array of `[key, value]`
// pairs, or two parallel arrays of the same length -- one of keys, and one of
// the corresponding values.
_.object = function(list, values) {
var result = {};
for (var i = 0, length = getLength(list); i < length; i++) {
if (values) {
result[list[i]] = values[i];
} else {
result[list[i][0]] = list[i][1];
}
}
return result;
};
// Generator function to create the findIndex and findLastIndex functions
function createPredicateIndexFinder(dir) {
return function(array, predicate, context) {
predicate = cb(predicate, context);
var length = getLength(array);
var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) {
if (predicate(array[index], index, array)) return index;
}
return -1;
};
}
// Returns the first index on an array-like that passes a predicate test
_.findIndex = createPredicateIndexFinder(1);
_.findLastIndex = createPredicateIndexFinder(-1);
// Use a comparator function to figure out the smallest index at which
// an object should be inserted so as to maintain order. Uses binary search.
_.sortedIndex = function(array, obj, iteratee, context) {
iteratee = cb(iteratee, context, 1);
var value = iteratee(obj);
var low = 0, high = getLength(array);
while (low < high) {
var mid = Math.floor((low + high) / 2);
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
}
return low;
};
// Generator function to create the indexOf and lastIndexOf functions
function createIndexFinder(dir, predicateFind, sortedIndex) {
return function(array, item, idx) {
var i = 0, length = getLength(array);
if (typeof idx == 'number') {
if (dir > 0) {
i = idx >= 0 ? idx : Math.max(idx + length, i);
} else {
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
}
} else if (sortedIndex && idx && length) {
idx = sortedIndex(array, item);
return array[idx] === item ? idx : -1;
}
if (item !== item) {
idx = predicateFind(slice.call(array, i, length), _.isNaN);
return idx >= 0 ? idx + i : -1;
}
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
if (array[idx] === item) return idx;
}
return -1;
};
}
// Return the position of the first occurrence of an item in an array,
// or -1 if the item is not included in the array.
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
// Generate an integer Array containing an arithmetic progression. A port of
// the native Python `range()` function. See
// [the Python documentation](http://docs.python.org/library/functions.html#range).
_.range = function(start, stop, step) {
if (stop == null) {
stop = start || 0;
start = 0;
}
step = step || 1;
var length = Math.max(Math.ceil((stop - start) / step), 0);
var range = Array(length);
for (var idx = 0; idx < length; idx++, start += step) {
range[idx] = start;
}
return range;
};
// Function (ahem) Functions
// ------------------
// Determines whether to execute a function as a constructor
// or a normal function with the provided arguments
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
var self = baseCreate(sourceFunc.prototype);
var result = sourceFunc.apply(self, args);
if (_.isObject(result)) return result;
return self;
};
// Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// available.
_.bind = function(func, context) {
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
var args = slice.call(arguments, 2);
var bound = function() {
return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
};
return bound;
};
// Partially apply a function by creating a version that has had some of its
// arguments pre-filled, without changing its dynamic `this` context. _ acts
// as a placeholder, allowing any combination of arguments to be pre-filled.
_.partial = function(func) {
var boundArgs = slice.call(arguments, 1);
var bound = function() {
var position = 0, length = boundArgs.length;
var args = Array(length);
for (var i = 0; i < length; i++) {
args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
}
while (position < arguments.length) args.push(arguments[position++]);
return executeBound(func, bound, this, this, args);
};
return bound;
};
// Bind a number of an object's methods to that object. Remaining arguments
// are the method names to be bound. Useful for ensuring that all callbacks
// defined on an object belong to it.
_.bindAll = function(obj) {
var i, length = arguments.length, key;
if (length <= 1) throw new Error('bindAll must be passed function names');
for (i = 1; i < length; i++) {
key = arguments[i];
obj[key] = _.bind(obj[key], obj);
}
return obj;
};
// Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) {
var memoize = function(key) {
var cache = memoize.cache;
var address = '' + (hasher ? hasher.apply(this, arguments) : key);
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
return cache[address];
};
memoize.cache = {};
return memoize;
};
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
_.delay = function(func, wait) {
var args = slice.call(arguments, 2);
return setTimeout(function(){
return func.apply(null, args);
}, wait);
};
// Defers a function, scheduling it to run after the current call stack has
// cleared.
_.defer = _.partial(_.delay, _, 1);
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time. Normally, the throttled function will run
// as much as it can, without ever going more than once per `wait` duration;
// but if you'd like to disable the execution on the leading edge, pass
// `{leading: false}`. To disable execution on the trailing edge, ditto.
_.throttle = function(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function() {
var now = _.now();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
};
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, args, context, timestamp, result;
var later = function() {
var last = _.now() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};
return function() {
context = this;
args = arguments;
timestamp = _.now();
var callNow = immediate && !timeout;
if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result;
};
};
// Returns the first function passed as an argument to the second,
// allowing you to adjust arguments, run code before and after, and
// conditionally execute the original function.
_.wrap = function(func, wrapper) {
return _.partial(wrapper, func);
};
// Returns a negated version of the passed-in predicate.
_.negate = function(predicate) {
return function() {
return !predicate.apply(this, arguments);
};
};
// Returns a function that is the composition of a list of functions, each
// consuming the return value of the function that follows.
_.compose = function() {
var args = arguments;
var start = args.length - 1;
return function() {
var i = start;
var result = args[start].apply(this, arguments);
while (i--) result = args[i].call(this, result);
return result;
};
};
// Returns a function that will only be executed on and after the Nth call.
_.after = function(times, func) {
return function() {
if (--times < 1) {
return func.apply(this, arguments);
}
};
};
// Returns a function that will only be executed up to (but not including) the Nth call.
_.before = function(times, func) {
var memo;
return function() {
if (--times > 0) {
memo = func.apply(this, arguments);
}
if (times <= 1) func = null;
return memo;
};
};
// Returns a function that will be executed at most one time, no matter how
// often you call it. Useful for lazy initialization.
_.once = _.partial(_.before, 2);
// Object Functions
// ----------------
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
function collectNonEnumProps(obj, keys) {
var nonEnumIdx = nonEnumerableProps.length;
var constructor = obj.constructor;
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
// Constructor is a special case.
var prop = 'constructor';
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
while (nonEnumIdx--) {
prop = nonEnumerableProps[nonEnumIdx];
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
keys.push(prop);
}
}
}
// Retrieve the names of an object's own properties.
// Delegates to **ECMAScript 5**'s native `Object.keys`
_.keys = function(obj) {
Iif (!_.isObject(obj)) return [];
Eif (nativeKeys) return nativeKeys(obj);
var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve all the property names of an object.
_.allKeys = function(obj) {
if (!_.isObject(obj)) return [];
var keys = [];
for (var key in obj) keys.push(key);
// Ahem, IE < 9.
if (hasEnumBug) collectNonEnumProps(obj, keys);
return keys;
};
// Retrieve the values of an object's properties.
_.values = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
var values = Array(length);
for (var i = 0; i < length; i++) {
values[i] = obj[keys[i]];
}
return values;
};
// Returns the results of applying the iteratee to each element of the object
// In contrast to _.map it returns an object
_.mapObject = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = _.keys(obj),
length = keys.length,
results = {},
currentKey;
for (var index = 0; index < length; index++) {
currentKey = keys[index];
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
// Convert an object into a list of `[key, value]` pairs.
_.pairs = function(obj) {
var keys = _.keys(obj);
var length = keys.length;
var pairs = Array(length);
for (var i = 0; i < length; i++) {
pairs[i] = [keys[i], obj[keys[i]]];
}
return pairs;
};
// Invert the keys and values of an object. The values must be serializable.
_.invert = function(obj) {
var result = {};
var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
result[obj[keys[i]]] = keys[i];
}
return result;
};
// Return a sorted list of the function names available on the object.
// Aliased as `methods`
_.functions = _.methods = function(obj) {
var names = [];
for (var key in obj) {
if (_.isFunction(obj[key])) names.push(key);
}
return names.sort();
};
// Extend a given object with all the properties in passed-in object(s).
_.extend = createAssigner(_.allKeys);
// Assigns a given object with all the own properties in the passed-in object(s)
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
_.extendOwn = _.assign = createAssigner(_.keys);
// Returns the first key on an object that passes a predicate test
_.findKey = function(obj, predicate, context) {
predicate = cb(predicate, context);
var keys = _.keys(obj), key;
for (var i = 0, length = keys.length; i < length; i++) {
key = keys[i];
if (predicate(obj[key], key, obj)) return key;
}
};
// Return a copy of the object only containing the whitelisted properties.
_.pick = function(object, oiteratee, context) {
var result = {}, obj = object, iteratee, keys;
if (obj == null) return result;
if (_.isFunction(oiteratee)) {
keys = _.allKeys(obj);
iteratee = optimizeCb(oiteratee, context);
} else {
keys = flatten(arguments, false, false, 1);
iteratee = function(value, key, obj) { return key in obj; };
obj = Object(obj);
}
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
var value = obj[key];
if (iteratee(value, key, obj)) result[key] = value;
}
return result;
};
// Return a copy of the object without the blacklisted properties.
_.omit = function(obj, iteratee, context) {
if (_.isFunction(iteratee)) {
iteratee = _.negate(iteratee);
} else {
var keys = _.map(flatten(arguments, false, false, 1), String);
iteratee = function(value, key) {
return !_.contains(keys, key);
};
}
return _.pick(obj, iteratee, context);
};
// Fill in a given object with default properties.
_.defaults = createAssigner(_.allKeys, true);
// Creates an object that inherits from the given prototype object.
// If additional properties are provided then they will be added to the
// created object.
_.create = function(prototype, props) {
var result = baseCreate(prototype);
if (props) _.extendOwn(result, props);
return result;
};
// Create a (shallow-cloned) duplicate of an object.
_.clone = function(obj) {
if (!_.isObject(obj)) return obj;
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
// Invokes interceptor with the obj, and then returns obj.
// The primary purpose of this method is to "tap into" a method chain, in
// order to perform operations on intermediate results within the chain.
_.tap = function(obj, interceptor) {
interceptor(obj);
return obj;
};
// Returns whether an object has a given set of `key:value` pairs.
_.isMatch = function(object, attrs) {
var keys = _.keys(attrs), length = keys.length;
if (object == null) return !length;
var obj = Object(object);
for (var i = 0; i < length; i++) {
var key = keys[i];
if (attrs[key] !== obj[key] || !(key in obj)) return false;
}
return true;
};
// Internal recursive comparison function for `isEqual`.
var eq = function(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a === 1 / b;
// A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b;
// Unwrap any wrapped objects.
if (a instanceof _) a = a._wrapped;
if (b instanceof _) b = b._wrapped;
// Compare `[[Class]]` names.
var className = toString.call(a);
if (className !== toString.call(b)) return false;
switch (className) {
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
case '[object RegExp]':
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case '[object String]':
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return '' + a === '' + b;
case '[object Number]':
// `NaN`s are equivalent, but non-reflexive.
// Object(NaN) is equivalent to NaN
if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case '[object Date]':
case '[object Boolean]':
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent.
return +a === +b;
}
var areArrays = className === '[object Array]';
if (!areArrays) {
if (typeof a != 'object' || typeof b != 'object') return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
_.isFunction(bCtor) && bCtor instanceof bCtor)
&& ('constructor' in a && 'constructor' in b)) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] === a) return bStack[length] === b;
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
// Recursively compare objects and arrays.
if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary.
length = a.length;
if (length !== b.length) return false;
// Deep compare the contents, ignoring non-numeric properties.
while (length--) {
if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} else {
// Deep compare objects.
var keys = _.keys(a), key;
length = keys.length;
// Ensure that both objects contain the same number of properties before comparing deep equality.
if (_.keys(b).length !== length) return false;
while (length--) {
// Deep compare each member
key = keys[length];
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
}
}
// Remove the first object from the stack of traversed objects.
aStack.pop();
bStack.pop();
return true;
};
// Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) {
return eq(a, b);
};
// Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties.
_.isEmpty = function(obj) {
if (obj == null) return true;
if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
return _.keys(obj).length === 0;
};
// Is a given value a DOM element?
_.isElement = function(obj) {
return !!(obj && obj.nodeType === 1);
};
// Is a given value an array?
// Delegates to ECMA5's native Array.isArray
_.isArray = nativeIsArray || function(obj) {
return toString.call(obj) === '[object Array]';
};
// Is a given variable an object?
_.isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
_['is' + name] = function(obj) {
return toString.call(obj) === '[object ' + name + ']';
};
});
// Define a fallback version of the method in browsers (ahem, IE < 9), where
// there isn't any inspectable "Arguments" type.
Iif (!_.isArguments(arguments)) {
_.isArguments = function(obj) {
return _.has(obj, 'callee');
};
}
// Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
// IE 11 (#1621), and in Safari 8 (#1929).
Eif (typeof /./ != 'function' && typeof Int8Array != 'object') {
_.isFunction = function(obj) {
return typeof obj == 'function' || false;
};
}
// Is a given object a finite number?
_.isFinite = function(obj) {
return isFinite(obj) && !isNaN(parseFloat(obj));
};
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
_.isNaN = function(obj) {
return _.isNumber(obj) && obj !== +obj;
};
// Is a given value a boolean?
_.isBoolean = function(obj) {
return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
};
// Is a given value equal to null?
_.isNull = function(obj) {
return obj === null;
};
// Is a given variable undefined?
_.isUndefined = function(obj) {
return obj === void 0;
};
// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
_.has = function(obj, key) {
return obj != null && hasOwnProperty.call(obj, key);
};
// Utility Functions
// -----------------
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
// previous owner. Returns a reference to the Underscore object.
_.noConflict = function() {
root._ = previousUnderscore;
return this;
};
// Keep the identity function around for default iteratees.
_.identity = function(value) {
return value;
};
// Predicate-generating functions. Often useful outside of Underscore.
_.constant = function(value) {
return function() {
return value;
};
};
_.noop = function(){};
_.property = property;
// Generates a function for a given object that returns a given property.
_.propertyOf = function(obj) {
return obj == null ? function(){} : function(key) {
return obj[key];
};
};
// Returns a predicate for checking whether an object has a given set of
// `key:value` pairs.
_.matcher = _.matches = function(attrs) {
attrs = _.extendOwn({}, attrs);
return function(obj) {
return _.isMatch(obj, attrs);
};
};
// Run a function **n** times.
_.times = function(n, iteratee, context) {
var accum = Array(Math.max(0, n));
iteratee = optimizeCb(iteratee, context, 1);
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
return accum;
};
// Return a random integer between min and max (inclusive).
_.random = function(min, max) {
if (max == null) {
max = min;
min = 0;
}
return min + Math.floor(Math.random() * (max - min + 1));
};
// A (possibly faster) way to get the current timestamp as an integer.
_.now = Date.now || function() {
return new Date().getTime();
};
// List of HTML entities for escaping.
var escapeMap = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'`': '`'
};
var unescapeMap = _.invert(escapeMap);
// Functions for escaping and unescaping strings to/from HTML interpolation.
var createEscaper = function(map) {
var escaper = function(match) {
return map[match];
};
// Regexes for identifying a key that needs to be escaped
var source = '(?:' + _.keys(map).join('|') + ')';
var testRegexp = RegExp(source);
var replaceRegexp = RegExp(source, 'g');
return function(string) {
string = string == null ? '' : '' + string;
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
};
};
_.escape = createEscaper(escapeMap);
_.unescape = createEscaper(unescapeMap);
// If the value of the named `property` is a function then invoke it with the
// `object` as context; otherwise, return it.
_.result = function(object, property, fallback) {
var value = object == null ? void 0 : object[property];
if (value === void 0) {
value = fallback;
}
return _.isFunction(value) ? value.call(object) : value;
};
// Generate a unique integer id (unique within the entire client session).
// Useful for temporary DOM ids.
var idCounter = 0;
_.uniqueId = function(prefix) {
var id = ++idCounter + '';
return prefix ? prefix + id : id;
};
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_.templateSettings = {
evaluate : /<%([\s\S]+?)%>/g,
interpolate : /<%=([\s\S]+?)%>/g,
escape : /<%-([\s\S]+?)%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var noMatch = /(.)^/;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
var escapeChar = function(match) {
return '\\' + escapes[match];
};
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
// NB: `oldSettings` only exists for backwards compatibility.
_.template = function(text, settings, oldSettings) {
if (!settings && oldSettings) settings = oldSettings;
settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation.
var matcher = RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
// Compile the template source, escaping string literals appropriately.
var index = 0;
var source = "__p+='";
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset).replace(escaper, escapeChar);
index = offset + match.length;
if (escape) {
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
} else if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
} else if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
// Adobe VMs need the match returned to produce the correct offest.
return match;
});
source += "';\n";
// If a variable is not specified, place data values in local scope.
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
source = "var __t,__p='',__j=Array.prototype.join," +
"print=function(){__p+=__j.call(arguments,'');};\n" +
source + 'return __p;\n';
try {
var render = new Function(settings.variable || 'obj', '_', source);
} catch (e) {
e.source = source;
throw e;
}
var template = function(data) {
return render.call(this, data, _);
};
// Provide the compiled source as a convenience for precompilation.
var argument = settings.variable || 'obj';
template.source = 'function(' + argument + '){\n' + source + '}';
return template;
};
// Add a "chain" function. Start chaining a wrapped Underscore object.
_.chain = function(obj) {
var instance = _(obj);
instance._chain = true;
return instance;
};
// OOP
// ---------------
// If Underscore is called as a function, it returns a wrapped object that
// can be used OO-style. This wrapper holds altered versions of all the
// underscore functions. Wrapped objects may be chained.
// Helper function to continue chaining intermediate results.
var result = function(instance, obj) {
return instance._chain ? _(obj).chain() : obj;
};
// Add your own custom functions to the Underscore object.
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = _[name] = obj[name];
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return result(this, func.apply(_, args));
};
});
};
// Add all of the Underscore functions to the wrapper object.
_.mixin(_);
// Add all mutator Array functions to the wrapper.
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name];
_.prototype[name] = function() {
var obj = this._wrapped;
method.apply(obj, arguments);
if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
return result(this, obj);
};
});
// Add all accessor Array functions to the wrapper.
_.each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name];
_.prototype[name] = function() {
return result(this, method.apply(this._wrapped, arguments));
};
});
// Extracts the result from a wrapped and chained object.
_.prototype.value = function() {
return this._wrapped;
};
// Provide unwrapping proxy for some methods used in engine operations
// such as arithmetic and JSON stringification.
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
_.prototype.toString = function() {
return '' + this._wrapped;
};
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
Iif (typeof define === 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
}
}.call(this));
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| ActionStack.js | 12.9% | (4 / 31) | 100% | (0 / 0) | 0% | (0 / 4) | 12.9% | (4 / 31) | |
| PlatformJson.js | 30.65% | (19 / 62) | 0% | (0 / 28) | 0% | (0 / 12) | 30.65% | (19 / 62) | |
| events.js | 100% | (1 / 1) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (1 / 1) | |
| superspawn.js | 17.28% | (14 / 81) | 0% | (0 / 48) | 0% | (0 / 9) | 17.5% | (14 / 80) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* jshint quotmark:false */
var events = require('./events'),
Q = require('q');
function ActionStack() {
this.stack = [];
this.completed = [];
}
ActionStack.prototype = {
createAction:function(handler, action_params, reverter, revert_params) {
return {
handler:{
run:handler,
params:action_params
},
reverter:{
run:reverter,
params:revert_params
}
};
},
push:function(tx) {
this.stack.push(tx);
},
// Returns a promise.
process:function(platform) {
events.emit('verbose', 'Beginning processing of action stack for ' + platform + ' project...');
while (this.stack.length) {
var action = this.stack.shift();
var handler = action.handler.run;
var action_params = action.handler.params;
try {
handler.apply(null, action_params);
} catch(e) {
events.emit('warn', 'Error during processing of action! Attempting to revert...');
this.stack.unshift(action);
var issue = 'Uh oh!\n';
// revert completed tasks
while(this.completed.length) {
var undo = this.completed.shift();
var revert = undo.reverter.run;
var revert_params = undo.reverter.params;
try {
revert.apply(null, revert_params);
} catch(err) {
events.emit('warn', 'Error during reversion of action! We probably really messed up your project now, sorry! D:');
issue += 'A reversion action failed: ' + err.message + '\n';
}
}
e.message = issue + e.message;
return Q.reject(e);
}
this.completed.push(action);
}
events.emit('verbose', 'Action stack processing complete.');
return Q();
}
};
module.exports = ActionStack;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/* jshint sub:true */
var fs = require('fs');
var path = require('path');
var shelljs = require('shelljs');
var mungeutil = require('./ConfigChanges/munge-util');
var pluginMappernto = require('cordova-registry-mapper').newToOld;
var pluginMapperotn = require('cordova-registry-mapper').oldToNew;
function PlatformJson(filePath, platform, root) {
this.filePath = filePath;
this.platform = platform;
this.root = fix_munge(root || {});
}
PlatformJson.load = function(plugins_dir, platform) {
var filePath = path.join(plugins_dir, platform + '.json');
var root = null;
if (fs.existsSync(filePath)) {
root = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
}
return new PlatformJson(filePath, platform, root);
};
PlatformJson.prototype.save = function() {
shelljs.mkdir('-p', path.dirname(this.filePath));
fs.writeFileSync(this.filePath, JSON.stringify(this.root, null, 4), 'utf-8');
};
/**
* Indicates whether the specified plugin is installed as a top-level (not as
* dependency to others)
* @method function
* @param {String} pluginId A plugin id to check for.
* @return {Boolean} true if plugin installed as top-level, otherwise false.
*/
PlatformJson.prototype.isPluginTopLevel = function(pluginId) {
var installedPlugins = this.root.installed_plugins;
return installedPlugins[pluginId] ||
installedPlugins[pluginMappernto[pluginId]] ||
installedPlugins[pluginMapperotn[pluginId]];
};
/**
* Indicates whether the specified plugin is installed as a dependency to other
* plugin.
* @method function
* @param {String} pluginId A plugin id to check for.
* @return {Boolean} true if plugin installed as a dependency, otherwise false.
*/
PlatformJson.prototype.isPluginDependent = function(pluginId) {
var dependentPlugins = this.root.dependent_plugins;
return dependentPlugins[pluginId] ||
dependentPlugins[pluginMappernto[pluginId]] ||
dependentPlugins[pluginMapperotn[pluginId]];
};
/**
* Indicates whether plugin is installed either as top-level or as dependency.
* @method function
* @param {String} pluginId A plugin id to check for.
* @return {Boolean} true if plugin installed, otherwise false.
*/
PlatformJson.prototype.isPluginInstalled = function(pluginId) {
return this.isPluginTopLevel(pluginId) ||
this.isPluginDependent(pluginId);
};
PlatformJson.prototype.addPlugin = function(pluginId, variables, isTopLevel) {
var pluginsList = isTopLevel ?
this.root.installed_plugins :
this.root.dependent_plugins;
pluginsList[pluginId] = variables;
return this;
};
PlatformJson.prototype.removePlugin = function(pluginId, isTopLevel) {
var pluginsList = isTopLevel ?
this.root.installed_plugins :
this.root.dependent_plugins;
delete pluginsList[pluginId];
return this;
};
PlatformJson.prototype.addInstalledPluginToPrepareQueue = function(pluginDirName, vars, is_top_level) {
this.root.prepare_queue.installed.push({'plugin':pluginDirName, 'vars':vars, 'topLevel':is_top_level});
};
PlatformJson.prototype.addUninstalledPluginToPrepareQueue = function(pluginId, is_top_level) {
this.root.prepare_queue.uninstalled.push({'plugin':pluginId, 'id':pluginId, 'topLevel':is_top_level});
};
/**
* Moves plugin, specified by id to top-level plugins. If plugin is top-level
* already, then does nothing.
* @method function
* @param {String} pluginId A plugin id to make top-level.
* @return {PlatformJson} PlatformJson instance.
*/
PlatformJson.prototype.makeTopLevel = function(pluginId) {
var plugin = this.root.dependent_plugins[pluginId];
if (plugin) {
delete this.root.dependent_plugins[pluginId];
this.root.installed_plugins[pluginId] = plugin;
}
return this;
};
// convert a munge from the old format ([file][parent][xml] = count) to the current one
function fix_munge(root) {
root.prepare_queue = root.prepare_queue || {installed:[], uninstalled:[]};
root.config_munge = root.config_munge || {files: {}};
root.installed_plugins = root.installed_plugins || {};
root.dependent_plugins = root.dependent_plugins || {};
var munge = root.config_munge;
if (!munge.files) {
var new_munge = { files: {} };
for (var file in munge) {
for (var selector in munge[file]) {
for (var xml_child in munge[file][selector]) {
var val = parseInt(munge[file][selector][xml_child]);
for (var i = 0; i < val; i++) {
mungeutil.deep_add(new_munge, [file, selector, { xml: xml_child, count: val }]);
}
}
}
}
root.config_munge = new_munge;
}
return root;
}
module.exports = PlatformJson;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
module.exports = new (require('events').EventEmitter)();
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var child_process = require('child_process');
var fs = require('fs');
var path = require('path');
var _ = require('underscore');
var Q = require('q');
var shell = require('shelljs');
var events = require('./events');
var iswin32 = process.platform == 'win32';
// On Windows, spawn() for batch files requires absolute path & having the extension.
function resolveWindowsExe(cmd) {
var winExtensions = ['.exe', '.cmd', '.bat', '.js', '.vbs'];
function isValidExe(c) {
return winExtensions.indexOf(path.extname(c)) !== -1 && fs.existsSync(c);
}
if (isValidExe(cmd)) {
return cmd;
}
cmd = shell.which(cmd) || cmd;
if (!isValidExe(cmd)) {
winExtensions.some(function(ext) {
if (fs.existsSync(cmd + ext)) {
cmd = cmd + ext;
return true;
}
});
}
return cmd;
}
function maybeQuote(a) {
if (/^[^"].*[ &].*[^"]/.test(a)) return '"' + a + '"';
return a;
}
// opts:
// printCommand: Whether to log the command (default: false)
// stdio: 'default' is to capture output and returning it as a string to success (same as exec)
// 'ignore' means don't bother capturing it
// 'inherit' means pipe the input & output. This is required for anything that prompts.
// env: Map of extra environment variables.
// cwd: Working directory for the command.
// chmod: If truthy, will attempt to set the execute bit before executing on non-Windows platforms.
// Returns a promise that succeeds only for return code = 0.
exports.spawn = function(cmd, args, opts) {
args = args || [];
opts = opts || {};
var spawnOpts = {};
var d = Q.defer();
if (iswin32) {
cmd = resolveWindowsExe(cmd);
// If we couldn't find the file, likely we'll end up failing,
// but for things like "del", cmd will do the trick.
if (path.extname(cmd) != '.exe') {
var cmdArgs = '"' + [cmd].concat(args).map(maybeQuote).join(' ') + '"';
// We need to use /s to ensure that spaces are parsed properly with cmd spawned content
args = [['/s', '/c', cmdArgs].join(' ')];
cmd = 'cmd';
spawnOpts.windowsVerbatimArguments = true;
} else if (!fs.existsSync(cmd)) {
// We need to use /s to ensure that spaces are parsed properly with cmd spawned content
args = ['/s', '/c', cmd].concat(args).map(maybeQuote);
}
}
if (opts.stdio == 'ignore') {
spawnOpts.stdio = 'ignore';
} else if (opts.stdio == 'inherit') {
spawnOpts.stdio = 'inherit';
}
if (opts.cwd) {
spawnOpts.cwd = opts.cwd;
}
if (opts.env) {
spawnOpts.env = _.extend(_.extend({}, process.env), opts.env);
}
if (opts.chmod && !iswin32) {
try {
// This fails when module is installed in a system directory (e.g. via sudo npm install)
fs.chmodSync(cmd, '755');
} catch (e) {
// If the perms weren't set right, then this will come as an error upon execution.
}
}
events.emit(opts.printCommand ? 'log' : 'verbose', 'Running command: ' + maybeQuote(cmd) + ' ' + args.map(maybeQuote).join(' '));
var child = child_process.spawn(cmd, args, spawnOpts);
var capturedOut = '';
var capturedErr = '';
if (child.stdout) {
child.stdout.setEncoding('utf8');
child.stdout.on('data', function(data) {
capturedOut += data;
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function(data) {
capturedErr += data;
});
}
child.on('close', whenDone);
child.on('error', whenDone);
function whenDone(arg) {
child.removeListener('close', whenDone);
child.removeListener('error', whenDone);
var code = typeof arg == 'number' ? arg : arg && arg.code;
events.emit('verbose', 'Command finished with error code ' + code + ': ' + cmd + ' ' + args);
if (code === 0) {
d.resolve(capturedOut.trim());
} else {
var errMsg = cmd + ': Command failed with exit code ' + code;
if (capturedErr) {
errMsg += ' Error output:\n' + capturedErr.trim();
}
var err = new Error(errMsg);
err.code = code;
d.reject(err);
}
}
return d.promise;
};
exports.maybeSpawn = function(cmd, args, opts) {
if (fs.existsSync(cmd)) {
return exports.spawn(cmd, args, opts);
}
return Q(null);
};
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| ConfigChanges.js | 14.84% | (19 / 128) | 0% | (0 / 46) | 0% | (0 / 21) | 14.96% | (19 / 127) | |
| ConfigFile.js | 17.48% | (18 / 103) | 0% | (0 / 46) | 0% | (0 / 8) | 17.82% | (18 / 101) | |
| ConfigKeeper.js | 26.09% | (6 / 23) | 0% | (0 / 8) | 0% | (0 / 4) | 27.27% | (6 / 22) | |
| munge-util.js | 11.11% | (8 / 72) | 0% | (0 / 42) | 0% | (0 / 13) | 11.11% | (8 / 72) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /*
*
* Copyright 2013 Anis Kadri
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/*
* This module deals with shared configuration / dependency "stuff". That is:
* - XML configuration files such as config.xml, AndroidManifest.xml or WMAppManifest.xml.
* - plist files in iOS
* Essentially, any type of shared resources that we need to handle with awareness
* of how potentially multiple plugins depend on a single shared resource, should be
* handled in this module.
*
* The implementation uses an object as a hash table, with "leaves" of the table tracking
* reference counts.
*/
/* jshint sub:true */
var fs = require('fs'),
path = require('path'),
et = require('elementtree'),
semver = require('semver'),
events = require('../events'),
ConfigKeeper = require('./ConfigKeeper');
var mungeutil = require('./munge-util');
exports.PlatformMunger = PlatformMunger;
exports.process = function(plugins_dir, project_dir, platform, platformJson, pluginInfoProvider) {
var munger = new PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider);
munger.process(plugins_dir);
munger.save_all();
};
/******************************************************************************
* PlatformMunger class
*
* Can deal with config file of a single project.
* Parsed config files are cached in a ConfigKeeper object.
******************************************************************************/
function PlatformMunger(platform, project_dir, platformJson, pluginInfoProvider) {
this.platform = platform;
this.project_dir = project_dir;
this.config_keeper = new ConfigKeeper(project_dir);
this.platformJson = platformJson;
this.pluginInfoProvider = pluginInfoProvider;
}
// Write out all unsaved files.
PlatformMunger.prototype.save_all = PlatformMunger_save_all;
function PlatformMunger_save_all() {
this.config_keeper.save_all();
this.platformJson.save();
}
// Apply a munge object to a single config file.
// The remove parameter tells whether to add the change or remove it.
PlatformMunger.prototype.apply_file_munge = PlatformMunger_apply_file_munge;
function PlatformMunger_apply_file_munge(file, munge, remove) {
var self = this;
for (var selector in munge.parents) {
for (var xml_child in munge.parents[selector]) {
// this xml child is new, graft it (only if config file exists)
var config_file = self.config_keeper.get(self.project_dir, self.platform, file);
if (config_file.exists) {
if (remove) config_file.prune_child(selector, munge.parents[selector][xml_child]);
else config_file.graft_child(selector, munge.parents[selector][xml_child]);
}
}
}
}
PlatformMunger.prototype.remove_plugin_changes = remove_plugin_changes;
function remove_plugin_changes(pluginInfo, is_top_level) {
var self = this;
var platform_config = self.platformJson.root;
var plugin_vars = is_top_level ?
platform_config.installed_plugins[pluginInfo.id] :
platform_config.dependent_plugins[pluginInfo.id];
// get config munge, aka how did this plugin change various config files
var config_munge = self.generate_plugin_config_munge(pluginInfo, plugin_vars);
// global munge looks at all plugins' changes to config files
var global_munge = platform_config.config_munge;
var munge = mungeutil.decrement_munge(global_munge, config_munge);
for (var file in munge.files) {
// CB-6976 Windows Universal Apps. Compatibility fix for existing plugins.
if (self.platform == 'windows' && file == 'package.appxmanifest' &&
!fs.existsSync(path.join(self.project_dir, 'package.appxmanifest'))) {
// New windows template separate manifest files for Windows8, Windows8.1 and WP8.1
var substs = ['package.phone.appxmanifest', 'package.windows.appxmanifest', 'package.windows80.appxmanifest', 'package.windows10.appxmanifest'];
/* jshint loopfunc:true */
substs.forEach(function(subst) {
events.emit('verbose', 'Applying munge to ' + subst);
self.apply_file_munge(subst, munge.files[file], true);
});
/* jshint loopfunc:false */
}
self.apply_file_munge(file, munge.files[file], /* remove = */ true);
}
// Remove from installed_plugins
self.platformJson.removePlugin(pluginInfo.id, is_top_level);
return self;
}
PlatformMunger.prototype.add_plugin_changes = add_plugin_changes;
function add_plugin_changes(pluginInfo, plugin_vars, is_top_level, should_increment) {
var self = this;
var platform_config = self.platformJson.root;
// get config munge, aka how should this plugin change various config files
var config_munge = self.generate_plugin_config_munge(pluginInfo, plugin_vars);
// global munge looks at all plugins' changes to config files
// TODO: The should_increment param is only used by cordova-cli and is going away soon.
// If should_increment is set to false, avoid modifying the global_munge (use clone)
// and apply the entire config_munge because it's already a proper subset of the global_munge.
var munge, global_munge;
if (should_increment) {
global_munge = platform_config.config_munge;
munge = mungeutil.increment_munge(global_munge, config_munge);
} else {
global_munge = mungeutil.clone_munge(platform_config.config_munge);
munge = config_munge;
}
for (var file in munge.files) {
// CB-6976 Windows Universal Apps. Compatibility fix for existing plugins.
if (self.platform == 'windows' && file == 'package.appxmanifest' &&
!fs.existsSync(path.join(self.project_dir, 'package.appxmanifest'))) {
var substs = ['package.phone.appxmanifest', 'package.windows.appxmanifest', 'package.windows80.appxmanifest', 'package.windows10.appxmanifest'];
/* jshint loopfunc:true */
substs.forEach(function(subst) {
events.emit('verbose', 'Applying munge to ' + subst);
self.apply_file_munge(subst, munge.files[file]);
});
/* jshint loopfunc:false */
}
self.apply_file_munge(file, munge.files[file]);
}
// Move to installed/dependent_plugins
self.platformJson.addPlugin(pluginInfo.id, plugin_vars || {}, is_top_level);
return self;
}
// Load the global munge from platform json and apply all of it.
// Used by cordova prepare to re-generate some config file from platform
// defaults and the global munge.
PlatformMunger.prototype.reapply_global_munge = reapply_global_munge ;
function reapply_global_munge () {
var self = this;
var platform_config = self.platformJson.root;
var global_munge = platform_config.config_munge;
for (var file in global_munge.files) {
self.apply_file_munge(file, global_munge.files[file]);
}
return self;
}
// generate_plugin_config_munge
// Generate the munge object from plugin.xml + vars
PlatformMunger.prototype.generate_plugin_config_munge = generate_plugin_config_munge;
function generate_plugin_config_munge(pluginInfo, vars) {
var self = this;
vars = vars || {};
var munge = { files: {} };
var changes = pluginInfo.getConfigFiles(self.platform);
// Demux 'package.appxmanifest' into relevant platform-specific appx manifests.
// Only spend the cycles if there are version-specific plugin settings
if (self.platform === 'windows' &&
changes.some(function(change) {
return ((typeof change.versions !== 'undefined') ||
(typeof change.deviceTarget !== 'undefined'));
}))
{
var manifests = {
'windows': {
'8.0.0': 'package.windows80.appxmanifest',
'8.1.0': 'package.windows.appxmanifest',
'10.0.0': 'package.windows10.appxmanifest'
},
'phone': {
'8.1.0': 'package.phone.appxmanifest',
'10.0.0': 'package.windows10.appxmanifest'
},
'all': {
'8.0.0': 'package.windows80.appxmanifest',
'8.1.0': ['package.windows.appxmanifest', 'package.phone.appxmanifest'],
'10.0.0': 'package.windows10.appxmanifest'
}
};
var oldChanges = changes;
changes = [];
oldChanges.forEach(function(change, changeIndex) {
// Only support semver/device-target demux for package.appxmanifest
// Pass through in case something downstream wants to use it
if (change.target !== 'package.appxmanifest') {
changes.push(change);
return;
}
var hasVersion = (typeof change.versions !== 'undefined');
var hasTargets = (typeof change.deviceTarget !== 'undefined');
// No semver/device-target for this config-file, pass it through
if (!(hasVersion || hasTargets)) {
changes.push(change);
return;
}
var targetDeviceSet = hasTargets ? change.deviceTarget : 'all';
if (['windows', 'phone', 'all'].indexOf(targetDeviceSet) === -1) {
// target-device couldn't be resolved, fix it up here to a valid value
targetDeviceSet = 'all';
}
var knownWindowsVersionsForTargetDeviceSet = Object.keys(manifests[targetDeviceSet]);
// at this point, 'change' targets package.appxmanifest and has a version attribute
knownWindowsVersionsForTargetDeviceSet.forEach(function(winver) {
// This is a local function that creates the new replacement representing the
// mutation. Used to save code further down.
var createReplacement = function(manifestFile, originalChange) {
var replacement = {
target: manifestFile,
parent: originalChange.parent,
after: originalChange.after,
xmls: originalChange.xmls,
versions: originalChange.versions,
deviceTarget: originalChange.deviceTarget
};
return replacement;
};
// version doesn't satisfy, so skip
if (hasVersion && !semver.satisfies(winver, change.versions)) {
return;
}
var versionSpecificManifests = manifests[targetDeviceSet][winver];
if (versionSpecificManifests.constructor === Array) {
// e.g. all['8.1.0'] === ['pkg.windows.appxmanifest', 'pkg.phone.appxmanifest']
versionSpecificManifests.forEach(function(manifestFile) {
changes.push(createReplacement(manifestFile, change));
});
}
else {
// versionSpecificManifests is actually a single string
changes.push(createReplacement(versionSpecificManifests, change));
}
});
});
}
changes.forEach(function(change) {
change.xmls.forEach(function(xml) {
// 1. stringify each xml
var stringified = (new et.ElementTree(xml)).write({xml_declaration:false});
// interp vars
if (vars) {
Object.keys(vars).forEach(function(key) {
var regExp = new RegExp('\\$' + key, 'g');
stringified = stringified.replace(regExp, vars[key]);
});
}
// 2. add into munge
mungeutil.deep_add(munge, change.target, change.parent, { xml: stringified, count: 1, after: change.after });
});
});
return munge;
}
// Go over the prepare queue and apply the config munges for each plugin
// that has been (un)installed.
PlatformMunger.prototype.process = PlatformMunger_process;
function PlatformMunger_process(plugins_dir) {
var self = this;
var platform_config = self.platformJson.root;
// Uninstallation first
platform_config.prepare_queue.uninstalled.forEach(function(u) {
var pluginInfo = self.pluginInfoProvider.get(path.join(plugins_dir, u.plugin));
self.remove_plugin_changes(pluginInfo, u.topLevel);
});
// Now handle installation
platform_config.prepare_queue.installed.forEach(function(u) {
var pluginInfo = self.pluginInfoProvider.get(path.join(plugins_dir, u.plugin));
self.add_plugin_changes(pluginInfo, u.vars, u.topLevel, true);
});
// Empty out installed/ uninstalled queues.
platform_config.prepare_queue.uninstalled = [];
platform_config.prepare_queue.installed = [];
}
/**** END of PlatformMunger ****/
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
var fs = require('fs');
var path = require('path');
var bplist = require('bplist-parser');
var et = require('elementtree');
var glob = require('glob');
var plist = require('plist');
var plist_helpers = require('../util/plist-helpers');
var xml_helpers = require('../util/xml-helpers');
/******************************************************************************
* ConfigFile class
*
* Can load and keep various types of config files. Provides some functionality
* specific to some file types such as grafting XML children. In most cases it
* should be instantiated by ConfigKeeper.
*
* For plugin.xml files use as:
* plugin_config = self.config_keeper.get(plugin_dir, '', 'plugin.xml');
*
* TODO: Consider moving it out to a separate file and maybe partially with
* overrides in platform handlers.
******************************************************************************/
function ConfigFile(project_dir, platform, file_tag) {
this.project_dir = project_dir;
this.platform = platform;
this.file_tag = file_tag;
this.is_changed = false;
this.load();
}
// ConfigFile.load()
ConfigFile.prototype.load = ConfigFile_load;
function ConfigFile_load() {
var self = this;
// config file may be in a place not exactly specified in the target
var filepath = self.filepath = resolveConfigFilePath(self.project_dir, self.platform, self.file_tag);
if ( !filepath || !fs.existsSync(filepath) ) {
self.exists = false;
return;
}
self.exists = true;
self.mtime = fs.statSync(self.filepath).mtime;
var ext = path.extname(filepath);
// Windows8 uses an appxmanifest, and wp8 will likely use
// the same in a future release
if (ext == '.xml' || ext == '.appxmanifest') {
self.type = 'xml';
self.data = xml_helpers.parseElementtreeSync(filepath);
} else {
// plist file
self.type = 'plist';
// TODO: isBinaryPlist() reads the file and then parse re-reads it again.
// We always write out text plist, not binary.
// Do we still need to support binary plist?
// If yes, use plist.parseStringSync() and read the file once.
self.data = isBinaryPlist(filepath) ?
bplist.parseBuffer(fs.readFileSync(filepath)) :
plist.parse(fs.readFileSync(filepath, 'utf8'));
}
}
ConfigFile.prototype.save = function ConfigFile_save() {
var self = this;
if (self.type === 'xml') {
fs.writeFileSync(self.filepath, self.data.write({indent: 4}), 'utf-8');
} else {
// plist
var regExp = new RegExp('<string>[ \t\r\n]+?</string>', 'g');
fs.writeFileSync(self.filepath, plist.build(self.data).replace(regExp, '<string></string>'));
}
self.is_changed = false;
};
ConfigFile.prototype.graft_child = function ConfigFile_graft_child(selector, xml_child) {
var self = this;
var filepath = self.filepath;
var result;
if (self.type === 'xml') {
var xml_to_graft = [et.XML(xml_child.xml)];
result = xml_helpers.graftXML(self.data, xml_to_graft, selector, xml_child.after);
if ( !result) {
throw new Error('grafting xml at selector "' + selector + '" from "' + filepath + '" during config install went bad :(');
}
} else {
// plist file
result = plist_helpers.graftPLIST(self.data, xml_child.xml, selector);
if ( !result ) {
throw new Error('grafting to plist "' + filepath + '" during config install went bad :(');
}
}
self.is_changed = true;
};
ConfigFile.prototype.prune_child = function ConfigFile_prune_child(selector, xml_child) {
var self = this;
var filepath = self.filepath;
var result;
if (self.type === 'xml') {
var xml_to_graft = [et.XML(xml_child.xml)];
result = xml_helpers.pruneXML(self.data, xml_to_graft, selector);
} else {
// plist file
result = plist_helpers.prunePLIST(self.data, xml_child.xml, selector);
}
if (!result) {
var err_msg = 'Pruning at selector "' + selector + '" from "' + filepath + '" went bad.';
throw new Error(err_msg);
}
self.is_changed = true;
};
// Some config-file target attributes are not qualified with a full leading directory, or contain wildcards.
// Resolve to a real path in this function.
// TODO: getIOSProjectname is slow because of glob, try to avoid calling it several times per project.
function resolveConfigFilePath(project_dir, platform, file) {
var filepath = path.join(project_dir, file);
var matches;
if (file.indexOf('*') > -1) {
// handle wildcards in targets using glob.
matches = glob.sync(path.join(project_dir, '**', file));
if (matches.length) filepath = matches[0];
// [CB-5989] multiple Info.plist files may exist. default to $PROJECT_NAME-Info.plist
if(matches.length > 1 && file.indexOf('-Info.plist')>-1){
var plistName = getIOSProjectname(project_dir)+'-Info.plist';
for (var i=0; i < matches.length; i++) {
if(matches[i].indexOf(plistName) > -1){
filepath = matches[i];
break;
}
}
}
return filepath;
}
// special-case config.xml target that is just "config.xml". This should be resolved to the real location of the file.
// TODO: move the logic that contains the locations of config.xml from cordova CLI into plugman.
if (file == 'config.xml') {
if (platform == 'ubuntu') {
filepath = path.join(project_dir, 'config.xml');
} else if (platform == 'ios') {
var iospath = getIOSProjectname(project_dir);
filepath = path.join(project_dir,iospath, 'config.xml');
} else if (platform == 'android') {
filepath = path.join(project_dir, 'res', 'xml', 'config.xml');
} else {
matches = glob.sync(path.join(project_dir, '**', 'config.xml'));
if (matches.length) filepath = matches[0];
}
return filepath;
}
// None of the special cases matched, returning project_dir/file.
return filepath;
}
// Find out the real name of an iOS project
// TODO: glob is slow, need a better way or caching, or avoid using more than once.
function getIOSProjectname(project_dir) {
var matches = glob.sync(path.join(project_dir, '*.xcodeproj'));
var iospath;
if (matches.length === 1) {
iospath = path.basename(matches[0],'.xcodeproj');
} else {
var msg;
if (matches.length === 0) {
msg = 'Does not appear to be an xcode project, no xcode project file in ' + project_dir;
} else {
msg = 'There are multiple *.xcodeproj dirs in ' + project_dir;
}
throw new Error(msg);
}
return iospath;
}
// determine if a plist file is binary
function isBinaryPlist(filename) {
// I wish there was a synchronous way to read only the first 6 bytes of a
// file. This is wasteful :/
var buf = '' + fs.readFileSync(filename, 'utf8');
// binary plists start with a magic header, "bplist"
return buf.substring(0, 6) === 'bplist';
}
module.exports = ConfigFile;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 1 1 1 1 1 1 | /*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/* jshint sub:true */
var path = require('path');
var ConfigFile = require('./ConfigFile');
/******************************************************************************
* ConfigKeeper class
*
* Used to load and store config files to avoid re-parsing and writing them out
* multiple times.
*
* The config files are referred to by a fake path constructed as
* project_dir/platform/file
* where file is the name used for the file in config munges.
******************************************************************************/
function ConfigKeeper(project_dir, plugins_dir) {
this.project_dir = project_dir;
this.plugins_dir = plugins_dir;
this._cached = {};
}
ConfigKeeper.prototype.get = function ConfigKeeper_get(project_dir, platform, file) {
var self = this;
// This fixes a bug with older plugins - when specifying config xml instead of res/xml/config.xml
// https://issues.apache.org/jira/browse/CB-6414
if(file == 'config.xml' && platform == 'android'){
file = 'res/xml/config.xml';
}
var fake_path = path.join(project_dir, platform, file);
if (self._cached[fake_path]) {
return self._cached[fake_path];
}
// File was not cached, need to load.
var config_file = new ConfigFile(project_dir, platform, file);
self._cached[fake_path] = config_file;
return config_file;
};
ConfigKeeper.prototype.save_all = function ConfigKeeper_save_all() {
var self = this;
Object.keys(self._cached).forEach(function (fake_path) {
var config_file = self._cached[fake_path];
if (config_file.is_changed) config_file.save();
});
};
module.exports = ConfigKeeper;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | 1 1 1 1 1 1 1 1 | /*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/* jshint sub:true */
var _ = require('underscore');
// add the count of [key1][key2]...[keyN] to obj
// return true if it didn't exist before
exports.deep_add = function deep_add(obj, keys /* or key1, key2 .... */ ) {
if ( !Array.isArray(keys) ) {
keys = Array.prototype.slice.call(arguments, 1);
}
return exports.process_munge(obj, true/*createParents*/, function (parentArray, k) {
var found = _.find(parentArray, function(element) {
return element.xml == k.xml;
});
if (found) {
found.after = found.after || k.after;
found.count += k.count;
} else {
parentArray.push(k);
}
return !found;
}, keys);
};
// decrement the count of [key1][key2]...[keyN] from obj and remove if it reaches 0
// return true if it was removed or not found
exports.deep_remove = function deep_remove(obj, keys /* or key1, key2 .... */ ) {
if ( !Array.isArray(keys) ) {
keys = Array.prototype.slice.call(arguments, 1);
}
var result = exports.process_munge(obj, false/*createParents*/, function (parentArray, k) {
var index = -1;
var found = _.find(parentArray, function (element) {
index++;
return element.xml == k.xml;
});
if (found) {
found.count -= k.count;
if (found.count > 0) {
return false;
}
else {
parentArray.splice(index, 1);
}
}
return undefined;
}, keys);
return typeof result === 'undefined' ? true : result;
};
// search for [key1][key2]...[keyN]
// return the object or undefined if not found
exports.deep_find = function deep_find(obj, keys /* or key1, key2 .... */ ) {
if ( !Array.isArray(keys) ) {
keys = Array.prototype.slice.call(arguments, 1);
}
return exports.process_munge(obj, false/*createParents?*/, function (parentArray, k) {
return _.find(parentArray, function (element) {
return element.xml == (k.xml || k);
});
}, keys);
};
// Execute func passing it the parent array and the xmlChild key.
// When createParents is true, add the file and parent items they are missing
// When createParents is false, stop and return undefined if the file and/or parent items are missing
exports.process_munge = function process_munge(obj, createParents, func, keys /* or key1, key2 .... */ ) {
if ( !Array.isArray(keys) ) {
keys = Array.prototype.slice.call(arguments, 1);
}
var k = keys[0];
if (keys.length == 1) {
return func(obj, k);
} else if (keys.length == 2) {
if (!obj.parents[k] && !createParents) {
return undefined;
}
obj.parents[k] = obj.parents[k] || [];
return exports.process_munge(obj.parents[k], createParents, func, keys.slice(1));
} else if (keys.length == 3){
if (!obj.files[k] && !createParents) {
return undefined;
}
obj.files[k] = obj.files[k] || { parents: {} };
return exports.process_munge(obj.files[k], createParents, func, keys.slice(1));
} else {
throw new Error('Invalid key format. Must contain at most 3 elements (file, parent, xmlChild).');
}
};
// All values from munge are added to base as
// base[file][selector][child] += munge[file][selector][child]
// Returns a munge object containing values that exist in munge
// but not in base.
exports.increment_munge = function increment_munge(base, munge) {
var diff = { files: {} };
for (var file in munge.files) {
for (var selector in munge.files[file].parents) {
for (var xml_child in munge.files[file].parents[selector]) {
var val = munge.files[file].parents[selector][xml_child];
// if node not in base, add it to diff and base
// else increment it's value in base without adding to diff
var newlyAdded = exports.deep_add(base, [file, selector, val]);
if (newlyAdded) {
exports.deep_add(diff, file, selector, val);
}
}
}
}
return diff;
};
// Update the base munge object as
// base[file][selector][child] -= munge[file][selector][child]
// nodes that reached zero value are removed from base and added to the returned munge
// object.
exports.decrement_munge = function decrement_munge(base, munge) {
var zeroed = { files: {} };
for (var file in munge.files) {
for (var selector in munge.files[file].parents) {
for (var xml_child in munge.files[file].parents[selector]) {
var val = munge.files[file].parents[selector][xml_child];
// if node not in base, add it to diff and base
// else increment it's value in base without adding to diff
var removed = exports.deep_remove(base, [file, selector, val]);
if (removed) {
exports.deep_add(zeroed, file, selector, val);
}
}
}
}
return zeroed;
};
// For better readability where used
exports.clone_munge = function clone_munge(munge) {
return exports.increment_munge({}, munge);
};
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| ConfigParser.js | 4.85% | (10 / 206) | 0% | (0 / 106) | 0% | (0 / 63) | 4.9% | (10 / 204) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | 1 1 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* jshint sub:true */
var et = require('elementtree'),
xml= require('../util/xml-helpers'),
CordovaError = require('../CordovaError/CordovaError'),
fs = require('fs'),
events = require('../events');
/** Wraps a config.xml file */
function ConfigParser(path) {
this.path = path;
try {
this.doc = xml.parseElementtreeSync(path);
this.cdvNamespacePrefix = getCordovaNamespacePrefix(this.doc);
et.register_namespace(this.cdvNamespacePrefix, 'http://cordova.apache.org/ns/1.0');
} catch (e) {
console.error('Parsing '+path+' failed');
throw e;
}
var r = this.doc.getroot();
if (r.tag !== 'widget') {
throw new CordovaError(path + ' has incorrect root node name (expected "widget", was "' + r.tag + '")');
}
}
function getNodeTextSafe(el) {
return el && el.text && el.text.trim();
}
function findOrCreate(doc, name) {
var ret = doc.find(name);
if (!ret) {
ret = new et.Element(name);
doc.getroot().append(ret);
}
return ret;
}
function getCordovaNamespacePrefix(doc){
var rootAtribs = Object.getOwnPropertyNames(doc.getroot().attrib);
var prefix = 'cdv';
for (var j = 0; j < rootAtribs.length; j++ ) {
if(rootAtribs[j].indexOf('xmlns:') === 0 &&
doc.getroot().attrib[rootAtribs[j]] === 'http://cordova.apache.org/ns/1.0'){
var strings = rootAtribs[j].split(':');
prefix = strings[1];
break;
}
}
return prefix;
}
/**
* Finds the value of an element's attribute
* @param {String} attributeName Name of the attribute to search for
* @param {Array} elems An array of ElementTree nodes
* @return {String}
*/
function findElementAttributeValue(attributeName, elems) {
elems = Array.isArray(elems) ? elems : [ elems ];
var value = elems.filter(function (elem) {
return elem.attrib.name.toLowerCase() === attributeName.toLowerCase();
}).map(function (filteredElems) {
return filteredElems.attrib.value;
}).pop();
return value ? value : '';
}
ConfigParser.prototype = {
packageName: function(id) {
return this.doc.getroot().attrib['id'];
},
setPackageName: function(id) {
this.doc.getroot().attrib['id'] = id;
},
android_packageName: function() {
return this.doc.getroot().attrib['android-packageName'];
},
android_activityName: function() {
return this.doc.getroot().attrib['android-activityName'];
},
ios_CFBundleIdentifier: function() {
return this.doc.getroot().attrib['ios-CFBundleIdentifier'];
},
name: function() {
return getNodeTextSafe(this.doc.find('name'));
},
setName: function(name) {
var el = findOrCreate(this.doc, 'name');
el.text = name;
},
description: function() {
return getNodeTextSafe(this.doc.find('description'));
},
setDescription: function(text) {
var el = findOrCreate(this.doc, 'description');
el.text = text;
},
version: function() {
return this.doc.getroot().attrib['version'];
},
windows_packageVersion: function() {
return this.doc.getroot().attrib('windows-packageVersion');
},
android_versionCode: function() {
return this.doc.getroot().attrib['android-versionCode'];
},
ios_CFBundleVersion: function() {
return this.doc.getroot().attrib['ios-CFBundleVersion'];
},
setVersion: function(value) {
this.doc.getroot().attrib['version'] = value;
},
author: function() {
return getNodeTextSafe(this.doc.find('author'));
},
getGlobalPreference: function (name) {
return findElementAttributeValue(name, this.doc.findall('preference'));
},
setGlobalPreference: function (name, value) {
var pref = this.doc.find('preference[@name="' + name + '"]');
if (!pref) {
pref = new et.Element('preference');
pref.attrib.name = name;
this.doc.getroot().append(pref);
}
pref.attrib.value = value;
},
getPlatformPreference: function (name, platform) {
return findElementAttributeValue(name, this.doc.findall('platform[@name=\'' + platform + '\']/preference'));
},
getPreference: function(name, platform) {
var platformPreference = '';
if (platform) {
platformPreference = this.getPlatformPreference(name, platform);
}
return platformPreference ? platformPreference : this.getGlobalPreference(name);
},
/**
* Returns all resources for the platform specified.
* @param {String} platform The platform.
* @param {string} resourceName Type of static resources to return.
* "icon" and "splash" currently supported.
* @return {Array} Resources for the platform specified.
*/
getStaticResources: function(platform, resourceName) {
var ret = [],
staticResources = [];
if (platform) { // platform specific icons
this.doc.findall('platform[@name=\'' + platform + '\']/' + resourceName).forEach(function(elt){
elt.platform = platform; // mark as platform specific resource
staticResources.push(elt);
});
}
// root level resources
staticResources = staticResources.concat(this.doc.findall(resourceName));
// parse resource elements
var that = this;
staticResources.forEach(function (elt) {
var res = {};
res.src = elt.attrib.src;
res.density = elt.attrib['density'] || elt.attrib[that.cdvNamespacePrefix+':density'] || elt.attrib['gap:density'];
res.platform = elt.platform || null; // null means icon represents default icon (shared between platforms)
res.width = +elt.attrib.width || undefined;
res.height = +elt.attrib.height || undefined;
// default icon
if (!res.width && !res.height && !res.density) {
ret.defaultResource = res;
}
ret.push(res);
});
/**
* Returns resource with specified width and/or height.
* @param {number} width Width of resource.
* @param {number} height Height of resource.
* @return {Resource} Resource object or null if not found.
*/
ret.getBySize = function(width, height) {
return ret.filter(function(res) {
if (!res.width && !res.height) {
return false;
}
return ((!res.width || (width == res.width)) &&
(!res.height || (height == res.height)));
})[0] || null;
};
/**
* Returns resource with specified density.
* @param {string} density Density of resource.
* @return {Resource} Resource object or null if not found.
*/
ret.getByDensity = function(density) {
return ret.filter(function(res) {
return res.density == density;
})[0] || null;
};
/** Returns default icons */
ret.getDefault = function() {
return ret.defaultResource;
};
return ret;
},
/**
* Returns all icons for specific platform.
* @param {string} platform Platform name
* @return {Resource[]} Array of icon objects.
*/
getIcons: function(platform) {
return this.getStaticResources(platform, 'icon');
},
/**
* Returns all splash images for specific platform.
* @param {string} platform Platform name
* @return {Resource[]} Array of Splash objects.
*/
getSplashScreens: function(platform) {
return this.getStaticResources(platform, 'splash');
},
/**
* Returns all hook scripts for the hook type specified.
* @param {String} hook The hook type.
* @param {Array} platforms Platforms to look for scripts into (root scripts will be included as well).
* @return {Array} Script elements.
*/
getHookScripts: function(hook, platforms) {
var self = this;
var scriptElements = self.doc.findall('./hook');
if(platforms) {
platforms.forEach(function (platform) {
scriptElements = scriptElements.concat(self.doc.findall('./platform[@name="' + platform + '"]/hook'));
});
}
function filterScriptByHookType(el) {
return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
}
return scriptElements.filter(filterScriptByHookType);
},
/**
* Returns a list of plugin (IDs).
*
* This function also returns any plugin's that
* were defined using the legacy <feature> tags.
* @return {string[]} Array of plugin IDs
*/
getPluginIdList: function () {
var plugins = this.doc.findall('plugin');
var result = plugins.map(function(plugin){
return plugin.attrib.name;
});
var features = this.doc.findall('feature');
features.forEach(function(element ){
var idTag = element.find('./param[@name="id"]');
if(idTag){
result.push(idTag.attrib.value);
}
});
return result;
},
getPlugins: function () {
return this.getPluginIdList().map(function (pluginId) {
return this.getPlugin(pluginId);
}, this);
},
/**
* Adds a plugin element. Does not check for duplicates.
* @name addPlugin
* @function
* @param {object} attributes name and spec are supported
* @param {Array|object} variables name, value or arbitary object
*/
addPlugin: function (attributes, variables) {
if (!attributes && !attributes.name) return;
var el = new et.Element('plugin');
el.attrib.name = attributes.name;
if (attributes.spec) {
el.attrib.spec = attributes.spec;
}
// support arbitrary object as variables source
if (variables && typeof variables === 'object' && !Array.isArray(variables)) {
variables = Object.keys(variables)
.map(function (variableName) {
return {name: variableName, value: variables[variableName]};
});
}
if (variables) {
variables.forEach(function (variable) {
el.append(new et.Element('variable', { name: variable.name, value: variable.value }));
});
}
this.doc.getroot().append(el);
},
/**
* Retrives the plugin with the given id or null if not found.
*
* This function also returns any plugin's that
* were defined using the legacy <feature> tags.
* @name getPlugin
* @function
* @param {String} id
* @returns {object} plugin including any variables
*/
getPlugin: function(id){
if(!id){
return undefined;
}
var pluginElement = this.doc.find('./plugin/[@name="' + id + '"]');
if (null === pluginElement) {
var legacyFeature = this.doc.find('./feature/param[@name="id"][@value="' + id + '"]/..');
if(legacyFeature){
events.emit('log', 'Found deprecated feature entry for ' + id +' in config.xml.');
return featureToPlugin(legacyFeature);
}
return undefined;
}
var plugin = {};
plugin.name = pluginElement.attrib.name;
plugin.spec = pluginElement.attrib.spec || pluginElement.attrib.src || pluginElement.attrib.version;
plugin.variables = {};
var variableElements = pluginElement.findall('variable');
variableElements.forEach(function(varElement){
var name = varElement.attrib.name;
var value = varElement.attrib.value;
if(name){
plugin.variables[name] = value;
}
});
return plugin;
},
/**
* Remove the plugin entry with give name (id).
*
* This function also operates on any plugin's that
* were defined using the legacy <feature> tags.
* @name removePlugin
* @function
* @param id name of the plugin
*/
removePlugin: function(id){
if(id){
var plugins = this.doc.findall('./plugin/[@name="' + id + '"]')
.concat(this.doc.findall('./feature/param[@name="id"][@value="' + id + '"]/..'));
var children = this.doc.getroot().getchildren();
plugins.forEach(function (plugin) {
var idx = children.indexOf(plugin);
if (idx > -1) {
children.splice(idx, 1);
}
});
}
},
// Add any element to the root
addElement: function(name, attributes) {
var el = et.Element(name);
for (var a in attributes) {
el.attrib[a] = attributes[a];
}
this.doc.getroot().append(el);
},
/**
* Adds an engine. Does not check for duplicates.
* @param {String} name the engine name
* @param {String} spec engine source location or version (optional)
*/
addEngine: function(name, spec){
if(!name) return;
var el = et.Element('engine');
el.attrib.name = name;
if(spec){
el.attrib.spec = spec;
}
this.doc.getroot().append(el);
},
/**
* Removes all the engines with given name
* @param {String} name the engine name.
*/
removeEngine: function(name){
var engines = this.doc.findall('./engine/[@name="' +name+'"]');
for(var i=0; i < engines.length; i++){
var children = this.doc.getroot().getchildren();
var idx = children.indexOf(engines[i]);
if(idx > -1){
children.splice(idx,1);
}
}
},
getEngines: function(){
var engines = this.doc.findall('./engine');
return engines.map(function(engine){
var spec = engine.attrib.spec || engine.attrib.version;
return {
'name': engine.attrib.name,
'spec': spec ? spec : null
};
});
},
/* Get all the access tags */
getAccesses: function() {
var accesses = this.doc.findall('./access');
return accesses.map(function(access){
var minimum_tls_version = access.attrib['minimum-tls-version']; /* String */
var requires_forward_secrecy = access.attrib['requires-forward-secrecy']; /* Boolean */
return {
'origin': access.attrib.origin,
'minimum_tls_version': minimum_tls_version,
'requires_forward_secrecy' : requires_forward_secrecy
};
});
},
/* Get all the allow-navigation tags */
getAllowNavigations: function() {
var allow_navigations = this.doc.findall('./allow-navigation');
return allow_navigations.map(function(allow_navigation){
var minimum_tls_version = allow_navigation.attrib['minimum-tls-version']; /* String */
var requires_forward_secrecy = allow_navigation.attrib['requires-forward-secrecy']; /* Boolean */
return {
'href': allow_navigation.attrib.href,
'minimum_tls_version': minimum_tls_version,
'requires_forward_secrecy' : requires_forward_secrecy
};
});
},
write:function() {
fs.writeFileSync(this.path, this.doc.write({indent: 4}), 'utf-8');
}
};
function featureToPlugin(featureElement) {
var plugin = {};
plugin.variables = [];
var pluginVersion,
pluginSrc;
var nodes = featureElement.findall('param');
nodes.forEach(function (element) {
var n = element.attrib.name;
var v = element.attrib.value;
if (n === 'id') {
plugin.name = v;
} else if (n === 'version') {
pluginVersion = v;
} else if (n === 'url' || n === 'installPath') {
pluginSrc = v;
} else {
plugin.variables[n] = v;
}
});
var spec = pluginSrc || pluginVersion;
if (spec) {
plugin.spec = spec;
}
return plugin;
}
module.exports = ConfigParser;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| CordovaError.js | 28.57% | (8 / 28) | 0% | (0 / 18) | 0% | (0 / 3) | 28.57% | (8 / 28) | |
| CordovaExternalToolErrorContext.js | 36.36% | (4 / 11) | 0% | (0 / 4) | 0% | (0 / 2) | 36.36% | (4 / 11) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* jshint proto:true */
var EOL = require('os').EOL;
/**
* A derived exception class. See usage example in cli.js
* Based on:
* stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript/8460753#8460753
* @param {String} message Error message
* @param {Number} [code=0] Error code
* @param {CordovaExternalToolErrorContext} [context] External tool error context object
* @constructor
*/
function CordovaError(message, code, context) {
Error.captureStackTrace(this, this.constructor);
this.name = this.constructor.name;
this.message = message;
this.code = code || CordovaError.UNKNOWN_ERROR;
this.context = context;
}
CordovaError.prototype.__proto__ = Error.prototype;
// TODO: Extend error codes according the projects specifics
CordovaError.UNKNOWN_ERROR = 0;
CordovaError.EXTERNAL_TOOL_ERROR = 1;
/**
* Translates instance's error code number into error code name, e.g. 0 -> UNKNOWN_ERROR
* @returns {string} Error code string name
*/
CordovaError.prototype.getErrorCodeName = function() {
for(var key in CordovaError) {
if(CordovaError.hasOwnProperty(key)) {
if(CordovaError[key] === this.code) {
return key;
}
}
}
};
/**
* Converts CordovaError instance to string representation
* @param {Boolean} [isVerbose] Set up verbose mode. Used to provide more
* details including information about error code name and context
* @return {String} Stringified error representation
*/
CordovaError.prototype.toString = function(isVerbose) {
var message = '', codePrefix = '';
if(this.code !== CordovaError.UNKNOWN_ERROR) {
codePrefix = 'code: ' + this.code + (isVerbose ? (' (' + this.getErrorCodeName() + ')') : '') + ' ';
}
if(this.code === CordovaError.EXTERNAL_TOOL_ERROR) {
if(typeof this.context !== 'undefined') {
if(isVerbose) {
message = codePrefix + EOL + this.context.toString(isVerbose) + '\n failed with an error: ' +
this.message + EOL + 'Stack trace: ' + this.stack;
} else {
message = codePrefix + '\'' + this.context.toString(isVerbose) + '\' ' + this.message;
}
} else {
message = 'External tool failed with an error: ' + this.message;
}
} else {
message = isVerbose ? codePrefix + this.stack : codePrefix + this.message;
}
return message;
};
module.exports = CordovaError;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* jshint proto:true */
var path = require('path');
/**
* @param {String} cmd Command full path
* @param {String[]} args Command args
* @param {String} [cwd] Command working directory
* @constructor
*/
function CordovaExternalToolErrorContext(cmd, args, cwd) {
this.cmd = cmd;
// Helper field for readability
this.cmdShortName = path.basename(cmd);
this.args = args;
this.cwd = cwd;
}
CordovaExternalToolErrorContext.prototype.toString = function(isVerbose) {
if(isVerbose) {
return 'External tool \'' + this.cmdShortName + '\'' +
'\nCommand full path: ' + this.cmd + '\nCommand args: ' + this.args +
(typeof this.cwd !== 'undefined' ? '\nCommand cwd: ' + this.cwd : '');
}
return this.cmdShortName;
};
module.exports = CordovaExternalToolErrorContext;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| PluginInfo.js | 17.72% | (28 / 158) | 0% | (0 / 45) | 0% | (0 / 43) | 17.83% | (28 / 157) | |
| PluginInfoProvider.js | 28.57% | (10 / 35) | 0% | (0 / 10) | 0% | (0 / 6) | 28.57% | (10 / 35) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* jshint sub:true, laxcomma:true, laxbreak:true */
/*
A class for holidng the information currently stored in plugin.xml
It should also be able to answer questions like whether the plugin
is compatible with a given engine version.
TODO (kamrik): refactor this to not use sync functions and return promises.
*/
var path = require('path')
, fs = require('fs')
, xml_helpers = require('../util/xml-helpers')
, CordovaError = require('../CordovaError/CordovaError')
;
function PluginInfo(dirname) {
var self = this;
// METHODS
// Defined inside the constructor to avoid the "this" binding problems.
// <preference> tag
// Example: <preference name="API_KEY" />
// Used to require a variable to be specified via --variable when installing the plugin.
self.getPreferences = getPreferences;
function getPreferences(platform) {
var arprefs = _getTags(self._et, 'preference', platform, _parsePreference);
var prefs= {};
for(var i in arprefs)
{
var pref=arprefs[i];
prefs[pref.preference]=pref.default;
}
// returns { key : default | null}
return prefs;
}
function _parsePreference(prefTag) {
var name = prefTag.attrib.name.toUpperCase();
var def = prefTag.attrib.default || null;
return {preference: name, default: def};
}
// <asset>
self.getAssets = getAssets;
function getAssets(platform) {
var assets = _getTags(self._et, 'asset', platform, _parseAsset);
return assets;
}
function _parseAsset(tag) {
var src = tag.attrib.src;
var target = tag.attrib.target;
if ( !src || !target) {
var msg =
'Malformed <asset> tag. Both "src" and "target" attributes'
+ 'must be specified in\n'
+ self.filepath
;
throw new Error(msg);
}
var asset = {
itemType: 'asset',
src: src,
target: target
};
return asset;
}
// <dependency>
// Example:
// <dependency id="com.plugin.id"
// url="https://github.com/myuser/someplugin"
// commit="428931ada3891801"
// subdir="some/path/here" />
self.getDependencies = getDependencies;
function getDependencies(platform) {
var deps = _getTags(
self._et,
'dependency',
platform,
_parseDependency
);
return deps;
}
function _parseDependency(tag) {
var dep =
{ id : tag.attrib.id
, url : tag.attrib.url || ''
, subdir : tag.attrib.subdir || ''
, commit : tag.attrib.commit
};
dep.git_ref = dep.commit;
if ( !dep.id ) {
var msg =
'<dependency> tag is missing id attribute in '
+ self.filepath
;
throw new CordovaError(msg);
}
return dep;
}
// <config-file> tag
self.getConfigFiles = getConfigFiles;
function getConfigFiles(platform) {
var configFiles = _getTags(self._et, 'config-file', platform, _parseConfigFile);
return configFiles;
}
function _parseConfigFile(tag) {
var configFile =
{ target : tag.attrib['target']
, parent : tag.attrib['parent']
, after : tag.attrib['after']
, xmls : tag.getchildren()
// To support demuxing via versions
, versions : tag.attrib['versions']
, deviceTarget: tag.attrib['device-target']
};
return configFile;
}
// <info> tags, both global and within a <platform>
// TODO (kamrik): Do we ever use <info> under <platform>? Example wanted.
self.getInfo = getInfo;
function getInfo(platform) {
var infos = _getTags(
self._et,
'info',
platform,
function(elem) { return elem.text; }
);
// Filter out any undefined or empty strings.
infos = infos.filter(Boolean);
return infos;
}
// <source-file>
// Examples:
// <source-file src="src/ios/someLib.a" framework="true" />
// <source-file src="src/ios/someLib.a" compiler-flags="-fno-objc-arc" />
self.getSourceFiles = getSourceFiles;
function getSourceFiles(platform) {
var sourceFiles = _getTagsInPlatform(self._et, 'source-file', platform, _parseSourceFile);
return sourceFiles;
}
function _parseSourceFile(tag) {
return {
itemType: 'source-file',
src: tag.attrib.src,
framework: isStrTrue(tag.attrib.framework),
weak: isStrTrue(tag.attrib.weak),
compilerFlags: tag.attrib['compiler-flags'],
targetDir: tag.attrib['target-dir']
};
}
// <header-file>
// Example:
// <header-file src="CDVFoo.h" />
self.getHeaderFiles = getHeaderFiles;
function getHeaderFiles(platform) {
var headerFiles = _getTagsInPlatform(self._et, 'header-file', platform, function(tag) {
return {
itemType: 'header-file',
src: tag.attrib.src,
targetDir: tag.attrib['target-dir']
};
});
return headerFiles;
}
// <resource-file>
// Example:
// <resource-file src="FooPluginStrings.xml" target="res/values/FooPluginStrings.xml" device-target="win" arch="x86" versions=">=8.1" />
self.getResourceFiles = getResourceFiles;
function getResourceFiles(platform) {
var resourceFiles = _getTagsInPlatform(self._et, 'resource-file', platform, function(tag) {
return {
itemType: 'resource-file',
src: tag.attrib.src,
target: tag.attrib.target,
versions: tag.attrib.versions,
deviceTarget: tag.attrib['device-target'],
arch: tag.attrib.arch
};
});
return resourceFiles;
}
// <lib-file>
// Example:
// <lib-file src="src/BlackBerry10/native/device/libfoo.so" arch="device" />
self.getLibFiles = getLibFiles;
function getLibFiles(platform) {
var libFiles = _getTagsInPlatform(self._et, 'lib-file', platform, function(tag) {
return {
itemType: 'lib-file',
src: tag.attrib.src,
arch: tag.attrib.arch,
Include: tag.attrib.Include,
versions: tag.attrib.versions,
deviceTarget: tag.attrib['device-target'] || tag.attrib.target
};
});
return libFiles;
}
// <hook>
// Example:
// <hook type="before_build" src="scripts/beforeBuild.js" />
self.getHookScripts = getHookScripts;
function getHookScripts(hook, platforms) {
var scriptElements = self._et.findall('./hook');
if(platforms) {
platforms.forEach(function (platform) {
scriptElements = scriptElements.concat(self._et.findall('./platform[@name="' + platform + '"]/hook'));
});
}
function filterScriptByHookType(el) {
return el.attrib.src && el.attrib.type && el.attrib.type.toLowerCase() === hook;
}
return scriptElements.filter(filterScriptByHookType);
}
self.getJsModules = getJsModules;
function getJsModules(platform) {
var modules = _getTags(self._et, 'js-module', platform, _parseJsModule);
return modules;
}
function _parseJsModule(tag) {
var ret = {
itemType: 'js-module',
name: tag.attrib.name,
src: tag.attrib.src,
clobbers: tag.findall('clobbers').map(function(tag) { return { target: tag.attrib.target }; }),
merges: tag.findall('merges').map(function(tag) { return { target: tag.attrib.target }; }),
runs: tag.findall('runs').length > 0
};
return ret;
}
self.getEngines = function() {
return self._et.findall('engines/engine').map(function(n) {
return {
name: n.attrib.name,
version: n.attrib.version,
platform: n.attrib.platform,
scriptSrc: n.attrib.scriptSrc
};
});
};
self.getPlatforms = function() {
return self._et.findall('platform').map(function(n) {
return { name: n.attrib.name };
});
};
self.getPlatformsArray = function() {
return self._et.findall('platform').map(function(n) {
return n.attrib.name;
});
};
self.getFrameworks = function(platform) {
return _getTags(self._et, 'framework', platform, function(el) {
var ret = {
itemType: 'framework',
type: el.attrib.type,
parent: el.attrib.parent,
custom: isStrTrue(el.attrib.custom),
src: el.attrib.src,
weak: isStrTrue(el.attrib.weak),
versions: el.attrib.versions,
targetDir: el.attrib['target-dir'],
deviceTarget: el.attrib['device-target'] || el.attrib.target,
arch: el.attrib.arch
};
return ret;
});
};
self.getFilesAndFrameworks = getFilesAndFrameworks;
function getFilesAndFrameworks(platform) {
// Please avoid changing the order of the calls below, files will be
// installed in this order.
var items = [].concat(
self.getSourceFiles(platform),
self.getHeaderFiles(platform),
self.getResourceFiles(platform),
self.getFrameworks(platform),
self.getLibFiles(platform)
);
return items;
}
///// End of PluginInfo methods /////
///// PluginInfo Constructor logic /////
self.filepath = path.join(dirname, 'plugin.xml');
if (!fs.existsSync(self.filepath)) {
throw new CordovaError('Cannot find plugin.xml for plugin \'' + path.basename(dirname) + '\'. Please try adding it again.');
}
self.dir = dirname;
var et = self._et = xml_helpers.parseElementtreeSync(self.filepath);
var pelem = et.getroot();
self.id = pelem.attrib.id;
self.version = pelem.attrib.version;
// Optional fields
self.name = pelem.findtext('name');
self.description = pelem.findtext('description');
self.license = pelem.findtext('license');
self.repo = pelem.findtext('repo');
self.issue = pelem.findtext('issue');
self.keywords = pelem.findtext('keywords');
self.info = pelem.findtext('info');
if (self.keywords) {
self.keywords = self.keywords.split(',').map( function(s) { return s.trim(); } );
}
self.getKeywordsAndPlatforms = function () {
var ret = self.keywords || [];
return ret.concat('ecosystem:cordova').concat(addCordova(self.getPlatformsArray()));
};
} // End of PluginInfo constructor.
// Helper function used to prefix every element of an array with cordova-
// Useful when we want to modify platforms to be cordova-platform
function addCordova(someArray) {
var newArray = someArray.map(function(element) {
return 'cordova-' + element;
});
return newArray;
}
// Helper function used by most of the getSomething methods of PluginInfo.
// Get all elements of a given name. Both in root and in platform sections
// for the given platform. If transform is given and is a function, it is
// applied to each element.
function _getTags(pelem, tag, platform, transform) {
var platformTag = pelem.find('./platform[@name="' + platform + '"]');
if (platform == 'windows' && !platformTag) {
platformTag = pelem.find('platform[@name="' + 'windows8' + '"]');
}
var tagsInRoot = pelem.findall(tag);
tagsInRoot = tagsInRoot || [];
var tagsInPlatform = platformTag ? platformTag.findall(tag) : [];
var tags = tagsInRoot.concat(tagsInPlatform);
if ( typeof transform === 'function' ) {
tags = tags.map(transform);
}
return tags;
}
// Same as _getTags() but only looks inside a platfrom section.
function _getTagsInPlatform(pelem, tag, platform, transform) {
var platformTag = pelem.find('./platform[@name="' + platform + '"]');
if (platform == 'windows' && !platformTag) {
platformTag = pelem.find('platform[@name="' + 'windows8' + '"]');
}
var tags = platformTag ? platformTag.findall(tag) : [];
if ( typeof transform === 'function' ) {
tags = tags.map(transform);
}
return tags;
}
// Check if x is a string 'true'.
function isStrTrue(x) {
return String(x).toLowerCase() == 'true';
}
module.exports = PluginInfo;
// Backwards compat:
PluginInfo.PluginInfo = PluginInfo;
PluginInfo.loadPluginsDir = function(dir) {
var PluginInfoProvider = require('./PluginInfoProvider');
return new PluginInfoProvider().getAllWithinSearchPath(dir);
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | 1 1 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/* jshint sub:true, laxcomma:true, laxbreak:true */
var fs = require('fs');
var path = require('path');
var PluginInfo = require('./PluginInfo');
var events = require('../events');
function PluginInfoProvider() {
this._cache = {};
this._getAllCache = {};
}
PluginInfoProvider.prototype.get = function(dirName) {
var absPath = path.resolve(dirName);
if (!this._cache[absPath]) {
this._cache[absPath] = new PluginInfo(dirName);
}
return this._cache[absPath];
};
// Normally you don't need to put() entries, but it's used
// when copying plugins, and in unit tests.
PluginInfoProvider.prototype.put = function(pluginInfo) {
var absPath = path.resolve(pluginInfo.dir);
this._cache[absPath] = pluginInfo;
};
// Used for plugin search path processing.
// Given a dir containing multiple plugins, create a PluginInfo object for
// each of them and return as array.
// Should load them all in parallel and return a promise, but not yet.
PluginInfoProvider.prototype.getAllWithinSearchPath = function(dirName) {
var absPath = path.resolve(dirName);
if (!this._getAllCache[absPath]) {
this._getAllCache[absPath] = getAllHelper(absPath, this);
}
return this._getAllCache[absPath];
};
function getAllHelper(absPath, provider) {
if (!fs.existsSync(absPath)){
return [];
}
// If dir itself is a plugin, return it in an array with one element.
if (fs.existsSync(path.join(absPath, 'plugin.xml'))) {
return [provider.get(absPath)];
}
var subdirs = fs.readdirSync(absPath);
var plugins = [];
subdirs.forEach(function(subdir) {
var d = path.join(absPath, subdir);
if (fs.existsSync(path.join(d, 'plugin.xml'))) {
try {
plugins.push(provider.get(d));
} catch (e) {
events.emit('warn', 'Error parsing ' + path.join(d, 'plugin.xml.\n' + e.stack));
}
}
});
return plugins;
}
module.exports = PluginInfoProvider;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| plist-helpers.js | 19.15% | (9 / 47) | 0% | (0 / 30) | 0% | (0 / 5) | 19.57% | (9 / 46) | |
| xml-helpers.js | 10.83% | (13 / 120) | 0% | (0 / 74) | 0% | (0 / 19) | 11.4% | (13 / 114) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 1 1 1 1 1 1 1 1 1 | /*
*
* Copyright 2013 Brett Rudd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
// contains PLIST utility functions
var __ = require('underscore');
var plist = require('plist');
// adds node to doc at selector
module.exports.graftPLIST = graftPLIST;
function graftPLIST(doc, xml, selector) {
var obj = plist.parse('<plist>'+xml+'</plist>');
var node = doc[selector];
if (node && Array.isArray(node) && Array.isArray(obj)){
node = node.concat(obj);
for (var i =0;i<node.length; i++){
for (var j=i+1; j<node.length; ++j) {
if (nodeEqual(node[i], node[j]))
node.splice(j--,1);
}
}
doc[selector] = node;
} else {
//plist uses objects for <dict>. If we have two dicts we merge them instead of
// overriding the old one. See CB-6472
if (node && __.isObject(node) && __.isObject(obj) && !__.isDate(node) && !__.isDate(obj)){//arrays checked above
__.extend(obj,node);
}
doc[selector] = obj;
}
return true;
}
// removes node from doc at selector
module.exports.prunePLIST = prunePLIST;
function prunePLIST(doc, xml, selector) {
var obj = plist.parse('<plist>'+xml+'</plist>');
pruneOBJECT(doc, selector, obj);
return true;
}
function pruneOBJECT(doc, selector, fragment) {
if (Array.isArray(fragment) && Array.isArray(doc[selector])) {
var empty = true;
for (var i in fragment) {
for (var j in doc[selector]) {
empty = pruneOBJECT(doc[selector], j, fragment[i]) && empty;
}
}
if (empty)
{
delete doc[selector];
return true;
}
}
else if (nodeEqual(doc[selector], fragment)) {
delete doc[selector];
return true;
}
return false;
}
function nodeEqual(node1, node2) {
if (typeof node1 != typeof node2)
return false;
else if (typeof node1 == 'string') {
node2 = escapeRE(node2).replace(new RegExp('\\$[a-zA-Z0-9-_]+','gm'),'(.*?)');
return new RegExp('^' + node2 + '$').test(node1);
}
else {
for (var key in node2) {
if (!nodeEqual(node1[key], node2[key])) return false;
}
return true;
}
}
// escape string for use in regex
function escapeRE(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '$&');
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | 1 1 1 1 1 1 1 1 1 1 1 1 1 | /*
*
* Copyright 2013 Anis Kadri
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/* jshint sub:true, laxcomma:true */
/**
* contains XML utility functions, some of which are specific to elementtree
*/
var fs = require('fs')
, path = require('path')
, _ = require('underscore')
, et = require('elementtree')
;
module.exports = {
// compare two et.XML nodes, see if they match
// compares tagName, text, attributes and children (recursively)
equalNodes: function(one, two) {
if (one.tag != two.tag) {
return false;
} else if (one.text.trim() != two.text.trim()) {
return false;
} else if (one._children.length != two._children.length) {
return false;
}
var oneAttribKeys = Object.keys(one.attrib),
twoAttribKeys = Object.keys(two.attrib),
i = 0, attribName;
if (oneAttribKeys.length != twoAttribKeys.length) {
return false;
}
for (i; i < oneAttribKeys.length; i++) {
attribName = oneAttribKeys[i];
if (one.attrib[attribName] != two.attrib[attribName]) {
return false;
}
}
for (i; i < one._children.length; i++) {
if (!module.exports.equalNodes(one._children[i], two._children[i])) {
return false;
}
}
return true;
},
// adds node to doc at selector, creating parent if it doesn't exist
graftXML: function(doc, nodes, selector, after) {
var parent = resolveParent(doc, selector);
if (!parent) {
//Try to create the parent recursively if necessary
try {
var parentToCreate = et.XML('<' + path.basename(selector) + '>'),
parentSelector = path.dirname(selector);
this.graftXML(doc, [parentToCreate], parentSelector);
} catch (e) {
return false;
}
parent = resolveParent(doc, selector);
if (!parent) return false;
}
nodes.forEach(function (node) {
// check if child is unique first
if (uniqueChild(node, parent)) {
var children = parent.getchildren();
var insertIdx = after ? findInsertIdx(children, after) : children.length;
//TODO: replace with parent.insert after the bug in ElementTree is fixed
parent.getchildren().splice(insertIdx, 0, node);
}
});
return true;
},
// removes node from doc at selector
pruneXML: function(doc, nodes, selector) {
var parent = resolveParent(doc, selector);
if (!parent) return false;
nodes.forEach(function (node) {
var matchingKid = null;
if ((matchingKid = findChild(node, parent)) !== null) {
// stupid elementtree takes an index argument it doesn't use
// and does not conform to the python lib
parent.remove(matchingKid);
}
});
return true;
},
parseElementtreeSync: function (filename) {
var contents = fs.readFileSync(filename, 'utf-8');
if(contents) {
//Windows is the BOM. Skip the Byte Order Mark.
contents = contents.substring(contents.indexOf('<'));
}
return new et.ElementTree(et.XML(contents));
}
};
function findChild(node, parent) {
var matchingKids = parent.findall(node.tag)
, i, j;
for (i = 0, j = matchingKids.length ; i < j ; i++) {
if (module.exports.equalNodes(node, matchingKids[i])) {
return matchingKids[i];
}
}
return null;
}
function uniqueChild(node, parent) {
var matchingKids = parent.findall(node.tag)
, i = 0;
if (matchingKids.length === 0) {
return true;
} else {
for (i; i < matchingKids.length; i++) {
if (module.exports.equalNodes(node, matchingKids[i])) {
return false;
}
}
return true;
}
}
var ROOT = /^\/([^\/]*)/,
ABSOLUTE = /^\/([^\/]*)\/(.*)/;
function resolveParent(doc, selector) {
var parent, tagName, subSelector;
// handle absolute selector (which elementtree doesn't like)
if (ROOT.test(selector)) {
tagName = selector.match(ROOT)[1];
// test for wildcard "any-tag" root selector
if (tagName == '*' || tagName === doc._root.tag) {
parent = doc._root;
// could be an absolute path, but not selecting the root
if (ABSOLUTE.test(selector)) {
subSelector = selector.match(ABSOLUTE)[2];
parent = parent.find(subSelector);
}
} else {
return false;
}
} else {
parent = doc.find(selector);
}
return parent;
}
// Find the index at which to insert an entry. After is a ;-separated priority list
// of tags after which the insertion should be made. E.g. If we need to
// insert an element C, and the rule is that the order of children has to be
// As, Bs, Cs. After will be equal to "C;B;A".
function findInsertIdx(children, after) {
var childrenTags = children.map(function(child) { return child.tag; });
var afters = after.split(';');
var afterIndexes = afters.map(function(current) { return childrenTags.lastIndexOf(current); });
var foundIndex = _.find(afterIndexes, function(index) { return index != -1; });
//add to the beginning if no matching nodes are found
return typeof foundIndex === 'undefined' ? 0 : foundIndex+1;
}
var BLACKLIST = ['platform', 'feature','plugin','engine'];
var SINGLETONS = ['content', 'author'];
function mergeXml(src, dest, platform, clobber) {
// Do nothing for blacklisted tags.
if (BLACKLIST.indexOf(src.tag) != -1) return;
//Handle attributes
Object.getOwnPropertyNames(src.attrib).forEach(function (attribute) {
if (clobber || !dest.attrib[attribute]) {
dest.attrib[attribute] = src.attrib[attribute];
}
});
//Handle text
if (src.text && (clobber || !dest.text)) {
dest.text = src.text;
}
//Handle platform
if (platform) {
src.findall('platform[@name="' + platform + '"]').forEach(function (platformElement) {
platformElement.getchildren().forEach(mergeChild);
});
}
//Handle children
src.getchildren().forEach(mergeChild);
function mergeChild (srcChild) {
var srcTag = srcChild.tag,
destChild = new et.Element(srcTag),
foundChild,
query = srcTag + '',
shouldMerge = true;
if (BLACKLIST.indexOf(srcTag) === -1) {
if (SINGLETONS.indexOf(srcTag) !== -1) {
foundChild = dest.find(query);
if (foundChild) {
destChild = foundChild;
dest.remove(destChild);
}
} else {
//Check for an exact match and if you find one don't add
Object.getOwnPropertyNames(srcChild.attrib).forEach(function (attribute) {
query += '[@' + attribute + '="' + srcChild.attrib[attribute] + '"]';
});
var foundChildren = dest.findall(query);
for(var i = 0; i < foundChildren.length; i++) {
foundChild = foundChildren[i];
if (foundChild && textMatch(srcChild, foundChild) && (Object.keys(srcChild.attrib).length==Object.keys(foundChild.attrib).length)) {
destChild = foundChild;
dest.remove(destChild);
shouldMerge = false;
break;
}
}
}
mergeXml(srcChild, destChild, platform, clobber && shouldMerge);
dest.append(destChild);
}
}
}
// Expose for testing.
module.exports.mergeXml = mergeXml;
function textMatch(elm1, elm2) {
var text1 = elm1.text ? elm1.text.replace(/\s+/, '') : '',
text2 = elm2.text ? elm2.text.replace(/\s+/, '') : '';
return (text1 === '' || text1 === text2);
}
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| constants.js | 100% | (2 / 2) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (2 / 2) | |
| elementpath.js | 16.15% | (26 / 161) | 0% | (0 / 66) | 0% | (0 / 24) | 16.15% | (26 / 161) | |
| elementtree.js | 23.53% | (72 / 306) | 0% | (0 / 134) | 0% | (0 / 64) | 23.61% | (72 / 305) | |
| errors.js | 55.56% | (5 / 9) | 0% | (0 / 2) | 0% | (0 / 1) | 55.56% | (5 / 9) | |
| parser.js | 57.14% | (4 / 7) | 0% | (0 / 2) | 0% | (0 / 1) | 57.14% | (4 / 7) | |
| sprintf.js | 13.79% | (4 / 29) | 0% | (0 / 9) | 0% | (0 / 2) | 13.79% | (4 / 29) | |
| treebuilder.js | 19.44% | (7 / 36) | 0% | (0 / 12) | 0% | (0 / 6) | 19.44% | (7 / 36) | |
| utils.js | 25% | (7 / 28) | 0% | (0 / 14) | 0% | (0 / 4) | 25% | (7 / 28) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 1 1 | /* * Copyright 2011 Rackspace * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ var DEFAULT_PARSER = 'sax'; exports.DEFAULT_PARSER = DEFAULT_PARSER; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /**
* Copyright 2011 Rackspace
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
var sprintf = require('./sprintf').sprintf;
var utils = require('./utils');
var SyntaxError = require('./errors').SyntaxError;
var _cache = {};
var RE = new RegExp(
"(" +
"'[^']*'|\"[^\"]*\"|" +
"::|" +
"//?|" +
"\\.\\.|" +
"\\(\\)|" +
"[/.*:\\[\\]\\(\\)@=])|" +
"((?:\\{[^}]+\\})?[^/\\[\\]\\(\\)@=\\s]+)|" +
"\\s+", 'g'
);
var xpath_tokenizer = utils.findall.bind(null, RE);
function prepare_tag(next, token) {
var tag = token[0];
function select(context, result) {
var i, len, elem, rv = [];
for (i = 0, len = result.length; i < len; i++) {
elem = result[i];
elem._children.forEach(function(e) {
if (e.tag === tag) {
rv.push(e);
}
});
}
return rv;
}
return select;
}
function prepare_star(next, token) {
function select(context, result) {
var i, len, elem, rv = [];
for (i = 0, len = result.length; i < len; i++) {
elem = result[i];
elem._children.forEach(function(e) {
rv.push(e);
});
}
return rv;
}
return select;
}
function prepare_dot(next, token) {
function select(context, result) {
var i, len, elem, rv = [];
for (i = 0, len = result.length; i < len; i++) {
elem = result[i];
rv.push(elem);
}
return rv;
}
return select;
}
function prepare_iter(next, token) {
var tag;
token = next();
if (token[1] === '*') {
tag = '*';
}
else if (!token[1]) {
tag = token[0] || '';
}
else {
throw new SyntaxError(token);
}
function select(context, result) {
var i, len, elem, rv = [];
for (i = 0, len = result.length; i < len; i++) {
elem = result[i];
elem.iter(tag, function(e) {
if (e !== elem) {
rv.push(e);
}
});
}
return rv;
}
return select;
}
function prepare_dot_dot(next, token) {
function select(context, result) {
var i, len, elem, rv = [], parent_map = context.parent_map;
if (!parent_map) {
context.parent_map = parent_map = {};
context.root.iter(null, function(p) {
p._children.forEach(function(e) {
parent_map[e] = p;
});
});
}
for (i = 0, len = result.length; i < len; i++) {
elem = result[i];
if (parent_map.hasOwnProperty(elem)) {
rv.push(parent_map[elem]);
}
}
return rv;
}
return select;
}
function prepare_predicate(next, token) {
var tag, key, value, select;
token = next();
if (token[1] === '@') {
// attribute
token = next();
if (token[1]) {
throw new SyntaxError(token, 'Invalid attribute predicate');
}
key = token[0];
token = next();
if (token[1] === ']') {
select = function(context, result) {
var i, len, elem, rv = [];
for (i = 0, len = result.length; i < len; i++) {
elem = result[i];
if (elem.get(key)) {
rv.push(elem);
}
}
return rv;
};
}
else if (token[1] === '=') {
value = next()[1];
if (value[0] === '"' || value[value.length - 1] === '\'') {
value = value.slice(1, value.length - 1);
}
else {
throw new SyntaxError(token, 'Ivalid comparison target');
}
token = next();
select = function(context, result) {
var i, len, elem, rv = [];
for (i = 0, len = result.length; i < len; i++) {
elem = result[i];
if (elem.get(key) === value) {
rv.push(elem);
}
}
return rv;
};
}
if (token[1] !== ']') {
throw new SyntaxError(token, 'Invalid attribute predicate');
}
}
else if (!token[1]) {
tag = token[0] || '';
token = next();
if (token[1] !== ']') {
throw new SyntaxError(token, 'Invalid node predicate');
}
select = function(context, result) {
var i, len, elem, rv = [];
for (i = 0, len = result.length; i < len; i++) {
elem = result[i];
if (elem.find(tag)) {
rv.push(elem);
}
}
return rv;
};
}
else {
throw new SyntaxError(null, 'Invalid predicate');
}
return select;
}
var ops = {
"": prepare_tag,
"*": prepare_star,
".": prepare_dot,
"..": prepare_dot_dot,
"//": prepare_iter,
"[": prepare_predicate,
};
function _SelectorContext(root) {
this.parent_map = null;
this.root = root;
}
function findall(elem, path) {
var selector, result, i, len, token, value, select, context;
if (_cache.hasOwnProperty(path)) {
selector = _cache[path];
}
else {
// TODO: Use smarter cache purging approach
if (Object.keys(_cache).length > 100) {
_cache = {};
}
if (path.charAt(0) === '/') {
throw new SyntaxError(null, 'Cannot use absolute path on element');
}
result = xpath_tokenizer(path);
selector = [];
function getToken() {
return result.shift();
}
token = getToken();
while (true) {
var c = token[1] || '';
value = ops[c](getToken, token);
if (!value) {
throw new SyntaxError(null, sprintf('Invalid path: %s', path));
}
selector.push(value);
token = getToken();
if (!token) {
break;
}
else if (token[1] === '/') {
token = getToken();
}
if (!token) {
break;
}
}
_cache[path] = selector;
}
// Execute slector pattern
result = [elem];
context = new _SelectorContext(elem);
for (i = 0, len = selector.length; i < len; i++) {
select = selector[i];
result = select(context, result);
}
return result || [];
}
function find(element, path) {
var resultElements = findall(element, path);
if (resultElements && resultElements.length > 0) {
return resultElements[0];
}
return null;
}
function findtext(element, path, defvalue) {
var resultElements = findall(element, path);
if (resultElements && resultElements.length > 0) {
return resultElements[0].text;
}
return defvalue;
}
exports.find = find;
exports.findall = findall;
exports.findtext = findtext;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /**
* Copyright 2011 Rackspace
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
var sprintf = require('./sprintf').sprintf;
var utils = require('./utils');
var ElementPath = require('./elementpath');
var TreeBuilder = require('./treebuilder').TreeBuilder;
var get_parser = require('./parser').get_parser;
var constants = require('./constants');
var element_ids = 0;
function Element(tag, attrib)
{
this._id = element_ids++;
this.tag = tag;
this.attrib = {};
this.text = null;
this.tail = null;
this._children = [];
if (attrib) {
this.attrib = utils.merge(this.attrib, attrib);
}
}
Element.prototype.toString = function()
{
return sprintf("<Element %s at %s>", this.tag, this._id);
};
Element.prototype.makeelement = function(tag, attrib)
{
return new Element(tag, attrib);
};
Element.prototype.len = function()
{
return this._children.length;
};
Element.prototype.getItem = function(index)
{
return this._children[index];
};
Element.prototype.setItem = function(index, element)
{
this._children[index] = element;
};
Element.prototype.delItem = function(index)
{
this._children.splice(index, 1);
};
Element.prototype.getSlice = function(start, stop)
{
return this._children.slice(start, stop);
};
Element.prototype.setSlice = function(start, stop, elements)
{
var i;
var k = 0;
for (i = start; i < stop; i++, k++) {
this._children[i] = elements[k];
}
};
Element.prototype.delSlice = function(start, stop)
{
this._children.splice(start, stop - start);
};
Element.prototype.append = function(element)
{
this._children.push(element);
};
Element.prototype.extend = function(elements)
{
this._children.concat(elements);
};
Element.prototype.insert = function(index, element)
{
this._children[index] = element;
};
Element.prototype.remove = function(element)
{
this._children = this._children.filter(function(e) {
/* TODO: is this the right way to do this? */
if (e._id === element._id) {
return false;
}
return true;
});
};
Element.prototype.getchildren = function() {
return this._children;
};
Element.prototype.find = function(path)
{
return ElementPath.find(this, path);
};
Element.prototype.findtext = function(path, defvalue)
{
return ElementPath.findtext(this, path, defvalue);
};
Element.prototype.findall = function(path, defvalue)
{
return ElementPath.findall(this, path, defvalue);
};
Element.prototype.clear = function()
{
this.attrib = {};
this._children = [];
this.text = null;
this.tail = null;
};
Element.prototype.get = function(key, defvalue)
{
if (this.attrib[key] !== undefined) {
return this.attrib[key];
}
else {
return defvalue;
}
};
Element.prototype.set = function(key, value)
{
this.attrib[key] = value;
};
Element.prototype.keys = function()
{
return Object.keys(this.attrib);
};
Element.prototype.items = function()
{
return utils.items(this.attrib);
};
/*
* In python this uses a generator, but in v8 we don't have em,
* so we use a callback instead.
**/
Element.prototype.iter = function(tag, callback)
{
var self = this;
var i, child;
if (tag === "*") {
tag = null;
}
if (tag === null || this.tag === tag) {
callback(self);
}
for (i = 0; i < this._children.length; i++) {
child = this._children[i];
child.iter(tag, function(e) {
callback(e);
});
}
};
Element.prototype.itertext = function(callback)
{
this.iter(null, function(e) {
if (e.text) {
callback(e.text);
}
if (e.tail) {
callback(e.tail);
}
});
};
function SubElement(parent, tag, attrib) {
var element = parent.makeelement(tag, attrib);
parent.append(element);
return element;
}
function Comment(text) {
var element = new Element(Comment);
if (text) {
element.text = text;
}
return element;
}
function CData(text) {
var element = new Element(CData);
if (text) {
element.text = text;
}
return element;
}
function ProcessingInstruction(target, text)
{
var element = new Element(ProcessingInstruction);
element.text = target;
if (text) {
element.text = element.text + " " + text;
}
return element;
}
function QName(text_or_uri, tag)
{
if (tag) {
text_or_uri = sprintf("{%s}%s", text_or_uri, tag);
}
this.text = text_or_uri;
}
QName.prototype.toString = function() {
return this.text;
};
function ElementTree(element)
{
this._root = element;
}
ElementTree.prototype.getroot = function() {
return this._root;
};
ElementTree.prototype._setroot = function(element) {
this._root = element;
};
ElementTree.prototype.parse = function(source, parser) {
if (!parser) {
parser = get_parser(constants.DEFAULT_PARSER);
parser = new parser.XMLParser(new TreeBuilder());
}
parser.feed(source);
this._root = parser.close();
return this._root;
};
ElementTree.prototype.iter = function(tag, callback) {
this._root.iter(tag, callback);
};
ElementTree.prototype.find = function(path) {
return this._root.find(path);
};
ElementTree.prototype.findtext = function(path, defvalue) {
return this._root.findtext(path, defvalue);
};
ElementTree.prototype.findall = function(path) {
return this._root.findall(path);
};
/**
* Unlike ElementTree, we don't write to a file, we return you a string.
*/
ElementTree.prototype.write = function(options) {
var sb = [];
options = utils.merge({
encoding: 'utf-8',
xml_declaration: null,
default_namespace: null,
method: 'xml'}, options);
if (options.xml_declaration !== false) {
sb.push("<?xml version='1.0' encoding='"+options.encoding +"'?>\n");
}
if (options.method === "text") {
_serialize_text(sb, self._root, encoding);
}
else {
var qnames, namespaces, indent, indent_string;
var x = _namespaces(this._root, options.encoding, options.default_namespace);
qnames = x[0];
namespaces = x[1];
if (options.hasOwnProperty('indent')) {
indent = 0;
indent_string = new Array(options.indent + 1).join(' ');
}
else {
indent = false;
}
if (options.method === "xml") {
_serialize_xml(function(data) {
sb.push(data);
}, this._root, options.encoding, qnames, namespaces, indent, indent_string);
}
else {
/* TODO: html */
throw new Error("unknown serialization method "+ options.method);
}
}
return sb.join("");
};
var _namespace_map = {
/* "well-known" namespace prefixes */
"http://www.w3.org/XML/1998/namespace": "xml",
"http://www.w3.org/1999/xhtml": "html",
"http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
"http://schemas.xmlsoap.org/wsdl/": "wsdl",
/* xml schema */
"http://www.w3.org/2001/XMLSchema": "xs",
"http://www.w3.org/2001/XMLSchema-instance": "xsi",
/* dublic core */
"http://purl.org/dc/elements/1.1/": "dc",
};
function register_namespace(prefix, uri) {
if (/ns\d+$/.test(prefix)) {
throw new Error('Prefix format reserved for internal use');
}
if (_namespace_map.hasOwnProperty(uri) && _namespace_map[uri] === prefix) {
delete _namespace_map[uri];
}
_namespace_map[uri] = prefix;
}
function _escape(text, encoding, isAttribute, isText) {
if (text) {
text = text.toString();
text = text.replace(/&/g, '&');
text = text.replace(/</g, '<');
text = text.replace(/>/g, '>');
if (!isText) {
text = text.replace(/\n/g, '
');
text = text.replace(/\r/g, '
');
}
if (isAttribute) {
text = text.replace(/"/g, '"');
}
}
return text;
}
/* TODO: benchmark single regex */
function _escape_attrib(text, encoding) {
return _escape(text, encoding, true);
}
function _escape_cdata(text, encoding) {
return _escape(text, encoding, false);
}
function _escape_text(text, encoding) {
return _escape(text, encoding, false, true);
}
function _namespaces(elem, encoding, default_namespace) {
var qnames = {};
var namespaces = {};
if (default_namespace) {
namespaces[default_namespace] = "";
}
function encode(text) {
return text;
}
function add_qname(qname) {
if (qname[0] === "{") {
var tmp = qname.substring(1).split("}", 2);
var uri = tmp[0];
var tag = tmp[1];
var prefix = namespaces[uri];
if (prefix === undefined) {
prefix = _namespace_map[uri];
if (prefix === undefined) {
prefix = "ns" + Object.keys(namespaces).length;
}
if (prefix !== "xml") {
namespaces[uri] = prefix;
}
}
if (prefix) {
qnames[qname] = sprintf("%s:%s", prefix, tag);
}
else {
qnames[qname] = tag;
}
}
else {
if (default_namespace) {
throw new Error('cannot use non-qualified names with default_namespace option');
}
qnames[qname] = qname;
}
}
elem.iter(null, function(e) {
var i;
var tag = e.tag;
var text = e.text;
var items = e.items();
if (tag instanceof QName && qnames[tag.text] === undefined) {
add_qname(tag.text);
}
else if (typeof(tag) === "string") {
add_qname(tag);
}
else if (tag !== null && tag !== Comment && tag !== CData && tag !== ProcessingInstruction) {
throw new Error('Invalid tag type for serialization: '+ tag);
}
if (text instanceof QName && qnames[text.text] === undefined) {
add_qname(text.text);
}
items.forEach(function(item) {
var key = item[0],
value = item[1];
if (key instanceof QName) {
key = key.text;
}
if (qnames[key] === undefined) {
add_qname(key);
}
if (value instanceof QName && qnames[value.text] === undefined) {
add_qname(value.text);
}
});
});
return [qnames, namespaces];
}
function _serialize_xml(write, elem, encoding, qnames, namespaces, indent, indent_string) {
var tag = elem.tag;
var text = elem.text;
var items;
var i;
var newlines = indent || (indent === 0);
write(Array(indent + 1).join(indent_string));
if (tag === Comment) {
write(sprintf("<!--%s-->", _escape_cdata(text, encoding)));
}
else if (tag === ProcessingInstruction) {
write(sprintf("<?%s?>", _escape_cdata(text, encoding)));
}
else if (tag === CData) {
text = text || '';
write(sprintf("<![CDATA[%s]]>", text));
}
else {
tag = qnames[tag];
if (tag === undefined) {
if (text) {
write(_escape_text(text, encoding));
}
elem.iter(function(e) {
_serialize_xml(write, e, encoding, qnames, null, newlines ? indent + 1 : false, indent_string);
});
}
else {
write("<" + tag);
items = elem.items();
if (items || namespaces) {
items.sort(); // lexical order
items.forEach(function(item) {
var k = item[0],
v = item[1];
if (k instanceof QName) {
k = k.text;
}
if (v instanceof QName) {
v = qnames[v.text];
}
else {
v = _escape_attrib(v, encoding);
}
write(sprintf(" %s=\"%s\"", qnames[k], v));
});
if (namespaces) {
items = utils.items(namespaces);
items.sort(function(a, b) { return a[1] < b[1]; });
items.forEach(function(item) {
var k = item[1],
v = item[0];
if (k) {
k = ':' + k;
}
write(sprintf(" xmlns%s=\"%s\"", k, _escape_attrib(v, encoding)));
});
}
}
if (text || elem.len()) {
if (text && text.toString().match(/^\s*$/)) {
text = null;
}
write(">");
if (!text && newlines) {
write("\n");
}
if (text) {
write(_escape_text(text, encoding));
}
elem._children.forEach(function(e) {
_serialize_xml(write, e, encoding, qnames, null, newlines ? indent + 1 : false, indent_string);
});
if (!text && indent) {
write(Array(indent + 1).join(indent_string));
}
write("</" + tag + ">");
}
else {
write(" />");
}
}
}
if (newlines) {
write("\n");
}
}
function parse(source, parser) {
var tree = new ElementTree();
tree.parse(source, parser);
return tree;
}
function tostring(element, options) {
return new ElementTree(element).write(options);
}
exports.PI = ProcessingInstruction;
exports.Comment = Comment;
exports.CData = CData;
exports.ProcessingInstruction = ProcessingInstruction;
exports.SubElement = SubElement;
exports.QName = QName;
exports.ElementTree = ElementTree;
exports.ElementPath = ElementPath;
exports.Element = function(tag, attrib) {
return new Element(tag, attrib);
};
exports.XML = function(data) {
var et = new ElementTree();
return et.parse(data);
};
exports.parse = parse;
exports.register_namespace = register_namespace;
exports.tostring = tostring;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 1 1 1 1 1 | /**
* Copyright 2011 Rackspace
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
var util = require('util');
var sprintf = require('./sprintf').sprintf;
function SyntaxError(token, msg) {
msg = msg || sprintf('Syntax Error at token %s', token.toString());
this.token = token;
this.message = msg;
Error.call(this, msg);
}
util.inherits(SyntaxError, Error);
exports.SyntaxError = SyntaxError;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 1 1 1 1 | /*
* Copyright 2011 Rackspace
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/* TODO: support node-expat C++ module optionally */
var util = require('util');
var parsers = require('./parsers/index');
function get_parser(name) {
if (name === 'sax') {
return parsers.sax;
}
else {
throw new Error('Invalid parser: ' + name);
}
}
exports.get_parser = get_parser;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 1 1 1 1 | /*
* Copyright 2011 Rackspace
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
var cache = {};
// Do any others need escaping?
var TO_ESCAPE = {
'\'': '\\\'',
'\n': '\\n'
};
function populate(formatter) {
var i, type,
key = formatter,
prev = 0,
arg = 1,
builder = 'return \'';
for (i = 0; i < formatter.length; i++) {
if (formatter[i] === '%') {
type = formatter[i + 1];
switch (type) {
case 's':
builder += formatter.slice(prev, i) + '\' + arguments[' + arg + '] + \'';
prev = i + 2;
arg++;
break;
case 'j':
builder += formatter.slice(prev, i) + '\' + JSON.stringify(arguments[' + arg + ']) + \'';
prev = i + 2;
arg++;
break;
case '%':
builder += formatter.slice(prev, i + 1);
prev = i + 2;
i++;
break;
}
} else if (TO_ESCAPE[formatter[i]]) {
builder += formatter.slice(prev, i) + TO_ESCAPE[formatter[i]];
prev = i + 1;
}
}
builder += formatter.slice(prev) + '\';';
cache[key] = new Function(builder);
}
/**
* A fast version of sprintf(), which currently only supports the %s and %j.
* This caches a formatting function for each format string that is used, so
* you should only use this sprintf() will be called many times with a single
* format string and a limited number of format strings will ever be used (in
* general this means that format strings should be string literals).
*
* @param {String} formatter A format string.
* @param {...String} var_args Values that will be formatted by %s and %j.
* @return {String} The formatted output.
*/
exports.sprintf = function(formatter, var_args) {
if (!cache[formatter]) {
populate(formatter);
}
return cache[formatter].apply(null, arguments);
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 1 1 1 1 1 1 1 | function TreeBuilder(element_factory) { this._data = []; this._elem = []; this._last = null; this._tail = null; if (!element_factory) { /* evil circular dep */ element_factory = require('./elementtree').Element; } this._factory = element_factory; } TreeBuilder.prototype.close = function() { return this._last; }; TreeBuilder.prototype._flush = function() { if (this._data) { if (this._last !== null) { var text = this._data.join(""); if (this._tail) { this._last.tail = text; } else { this._last.text = text; } } this._data = []; } }; TreeBuilder.prototype.data = function(data) { this._data.push(data); }; TreeBuilder.prototype.start = function(tag, attrs) { this._flush(); var elem = this._factory(tag, attrs); this._last = elem; if (this._elem.length) { this._elem[this._elem.length - 1].append(elem); } this._elem.push(elem); this._tail = null; }; TreeBuilder.prototype.end = function(tag) { this._flush(); this._last = this._elem.pop(); if (this._last.tag !== tag) { throw new Error("end tag mismatch"); } this._tail = 1; return this._last; }; exports.TreeBuilder = TreeBuilder; |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 1 1 1 1 1 1 1 | /**
* Copyright 2011 Rackspace
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
* @param {Object} hash.
* @param {Array} ignored.
*/
function items(hash, ignored) {
ignored = ignored || null;
var k, rv = [];
function is_ignored(key) {
if (!ignored || ignored.length === 0) {
return false;
}
return ignored.indexOf(key);
}
for (k in hash) {
if (hash.hasOwnProperty(k) && !(is_ignored(ignored))) {
rv.push([k, hash[k]]);
}
}
return rv;
}
function findall(re, str) {
var match, matches = [];
while ((match = re.exec(str))) {
matches.push(match);
}
return matches;
}
function merge(a, b) {
var c = {}, attrname;
for (attrname in a) {
if (a.hasOwnProperty(attrname)) {
c[attrname] = a[attrname];
}
}
for (attrname in b) {
if (b.hasOwnProperty(attrname)) {
c[attrname] = b[attrname];
}
}
return c;
}
exports.items = items;
exports.findall = findall;
exports.merge = merge;
|
| 1 2 3 | 1 | exports.sax = require('./sax');
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | var util = require('util');
var sax = require('sax');
var TreeBuilder = require('./../treebuilder').TreeBuilder;
function XMLParser(target) {
this.parser = sax.parser(true);
this.target = (target) ? target : new TreeBuilder();
this.parser.onopentag = this._handleOpenTag.bind(this);
this.parser.ontext = this._handleText.bind(this);
this.parser.oncdata = this._handleCdata.bind(this);
this.parser.ondoctype = this._handleDoctype.bind(this);
this.parser.oncomment = this._handleComment.bind(this);
this.parser.onclosetag = this._handleCloseTag.bind(this);
this.parser.onerror = this._handleError.bind(this);
}
XMLParser.prototype._handleOpenTag = function(tag) {
this.target.start(tag.name, tag.attributes);
};
XMLParser.prototype._handleText = function(text) {
this.target.data(text);
};
XMLParser.prototype._handleCdata = function(text) {
this.target.data(text);
};
XMLParser.prototype._handleDoctype = function(text) {
};
XMLParser.prototype._handleComment = function(comment) {
};
XMLParser.prototype._handleCloseTag = function(tag) {
this.target.end(tag);
};
XMLParser.prototype._handleError = function(err) {
throw err;
};
XMLParser.prototype.feed = function(chunk) {
this.parser.write(chunk);
};
XMLParser.prototype.close = function() {
this.parser.close();
return this.target.close();
};
exports.XMLParser = XMLParser;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| sax.js | 9.9% | (61 / 616) | 1.72% | (6 / 349) | 8.7% | (4 / 46) | 10.97% | (60 / 547) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 17 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 8 256 256 1 1 1 1 1 35 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | // wrapper for non-node envs
;(function (sax) {
sax.parser = function (strict, opt) { return new SAXParser(strict, opt) }
sax.SAXParser = SAXParser
sax.SAXStream = SAXStream
sax.createStream = createStream
// When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
// When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
// since that's the earliest that a buffer overrun could occur. This way, checks are
// as rare as required, but as often as necessary to ensure never crossing this bound.
// Furthermore, buffers are only tested at most once per write(), so passing a very
// large string into write() might have undesirable effects, but this is manageable by
// the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme
// edge case, result in creating at most one complete copy of the string passed in.
// Set to Infinity to have unlimited buffers.
sax.MAX_BUFFER_LENGTH = 64 * 1024
var buffers = [
"comment", "sgmlDecl", "textNode", "tagName", "doctype",
"procInstName", "procInstBody", "entity", "attribName",
"attribValue", "cdata", "script"
]
sax.EVENTS = // for discoverability.
[ "text"
, "processinginstruction"
, "sgmldeclaration"
, "doctype"
, "comment"
, "attribute"
, "opentag"
, "closetag"
, "opencdata"
, "cdata"
, "closecdata"
, "error"
, "end"
, "ready"
, "script"
, "opennamespace"
, "closenamespace"
]
function SAXParser (strict, opt) {
if (!(this instanceof SAXParser)) return new SAXParser(strict, opt)
var parser = this
clearBuffers(parser)
parser.q = parser.c = ""
parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
parser.opt = opt || {}
parser.tagCase = parser.opt.lowercasetags ? "toLowerCase" : "toUpperCase"
parser.tags = []
parser.closed = parser.closedRoot = parser.sawRoot = false
parser.tag = parser.error = null
parser.strict = !!strict
parser.noscript = !!(strict || parser.opt.noscript)
parser.state = S.BEGIN
parser.ENTITIES = Object.create(sax.ENTITIES)
parser.attribList = []
// namespaces form a prototype chain.
// it always points at the current tag,
// which protos to its parent tag.
if (parser.opt.xmlns) parser.ns = Object.create(rootNS)
// mostly just for error reporting
parser.position = parser.line = parser.column = 0
emit(parser, "onready")
}
Iif (!Object.create) Object.create = function (o) {
function f () { this.__proto__ = o }
f.prototype = o
return new f
}
Iif (!Object.getPrototypeOf) Object.getPrototypeOf = function (o) {
return o.__proto__
}
Iif (!Object.keys) Object.keys = function (o) {
var a = []
for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
return a
}
function checkBufferLength (parser) {
var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
, maxActual = 0
for (var i = 0, l = buffers.length; i < l; i ++) {
var len = parser[buffers[i]].length
if (len > maxAllowed) {
// Text/cdata nodes can get big, and since they're buffered,
// we can get here under normal conditions.
// Avoid issues by emitting the text node now,
// so at least it won't get any bigger.
switch (buffers[i]) {
case "textNode":
closeText(parser)
break
case "cdata":
emitNode(parser, "oncdata", parser.cdata)
parser.cdata = ""
break
case "script":
emitNode(parser, "onscript", parser.script)
parser.script = ""
break
default:
error(parser, "Max buffer length exceeded: "+buffers[i])
}
}
maxActual = Math.max(maxActual, len)
}
// schedule the next check for the earliest possible buffer overrun.
parser.bufferCheckPosition = (sax.MAX_BUFFER_LENGTH - maxActual)
+ parser.position
}
function clearBuffers (parser) {
for (var i = 0, l = buffers.length; i < l; i ++) {
parser[buffers[i]] = ""
}
}
SAXParser.prototype =
{ end: function () { end(this) }
, write: write
, resume: function () { this.error = null; return this }
, close: function () { return this.write(null) }
, end: function () { return this.write(null) }
}
try {
var Stream = require("stream").Stream
} catch (ex) {
var Stream = function () {}
}
var streamWraps = sax.EVENTS.filter(function (ev) {
return ev !== "error" && ev !== "end"
})
function createStream (strict, opt) {
return new SAXStream(strict, opt)
}
function SAXStream (strict, opt) {
if (!(this instanceof SAXStream)) return new SAXStream(strict, opt)
Stream.apply(me)
this._parser = new SAXParser(strict, opt)
this.writable = true
this.readable = true
var me = this
this._parser.onend = function () {
me.emit("end")
}
this._parser.onerror = function (er) {
me.emit("error", er)
// if didn't throw, then means error was handled.
// go ahead and clear error, so we can write again.
me._parser.error = null
}
streamWraps.forEach(function (ev) {
Object.defineProperty(me, "on" + ev, {
get: function () { return me._parser["on" + ev] },
set: function (h) {
if (!h) {
me.removeAllListeners(ev)
return me._parser["on"+ev] = h
}
me.on(ev, h)
},
enumerable: true,
configurable: false
})
})
}
SAXStream.prototype = Object.create(Stream.prototype,
{ constructor: { value: SAXStream } })
SAXStream.prototype.write = function (data) {
this._parser.write(data.toString())
this.emit("data", data)
return true
}
SAXStream.prototype.end = function (chunk) {
if (chunk && chunk.length) this._parser.write(chunk.toString())
this._parser.end()
return true
}
SAXStream.prototype.on = function (ev, handler) {
var me = this
if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) {
me._parser["on"+ev] = function () {
var args = arguments.length === 1 ? [arguments[0]]
: Array.apply(null, arguments)
args.splice(0, 0, ev)
me.emit.apply(me, args)
}
}
return Stream.prototype.on.call(me, ev, handler)
}
// character classes and tokens
var whitespace = "\r\n\t "
// this really needs to be replaced with character classes.
// XML allows all manner of ridiculous numbers and digits.
, number = "0124356789"
, letter = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// (Letter | "_" | ":")
, nameStart = letter+"_:"
, nameBody = nameStart+number+"-."
, quote = "'\""
, entity = number+letter+"#"
, attribEnd = whitespace + ">"
, CDATA = "[CDATA["
, DOCTYPE = "DOCTYPE"
, XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace"
, XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/"
, rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }
// turn all the string character sets into character class objects.
whitespace = charClass(whitespace)
number = charClass(number)
letter = charClass(letter)
nameStart = charClass(nameStart)
nameBody = charClass(nameBody)
quote = charClass(quote)
entity = charClass(entity)
attribEnd = charClass(attribEnd)
function charClass (str) {
return str.split("").reduce(function (s, c) {
s[c] = true
return s
}, {})
}
function is (charclass, c) {
return charclass[c]
}
function not (charclass, c) {
return !charclass[c]
}
var S = 0
sax.STATE =
{ BEGIN : S++
, TEXT : S++ // general stuff
, TEXT_ENTITY : S++ // & and such.
, OPEN_WAKA : S++ // <
, SGML_DECL : S++ // <!BLARG
, SGML_DECL_QUOTED : S++ // <!BLARG foo "bar
, DOCTYPE : S++ // <!DOCTYPE
, DOCTYPE_QUOTED : S++ // <!DOCTYPE "//blah
, DOCTYPE_DTD : S++ // <!DOCTYPE "//blah" [ ...
, DOCTYPE_DTD_QUOTED : S++ // <!DOCTYPE "//blah" [ "foo
, COMMENT_STARTING : S++ // <!-
, COMMENT : S++ // <!--
, COMMENT_ENDING : S++ // <!-- blah -
, COMMENT_ENDED : S++ // <!-- blah --
, CDATA : S++ // <![CDATA[ something
, CDATA_ENDING : S++ // ]
, CDATA_ENDING_2 : S++ // ]]
, PROC_INST : S++ // <?hi
, PROC_INST_BODY : S++ // <?hi there
, PROC_INST_QUOTED : S++ // <?hi "there
, PROC_INST_ENDING : S++ // <?hi "there" ?
, OPEN_TAG : S++ // <strong
, OPEN_TAG_SLASH : S++ // <strong /
, ATTRIB : S++ // <a
, ATTRIB_NAME : S++ // <a foo
, ATTRIB_NAME_SAW_WHITE : S++ // <a foo _
, ATTRIB_VALUE : S++ // <a foo=
, ATTRIB_VALUE_QUOTED : S++ // <a foo="bar
, ATTRIB_VALUE_UNQUOTED : S++ // <a foo=bar
, ATTRIB_VALUE_ENTITY_Q : S++ // <foo bar="""
, ATTRIB_VALUE_ENTITY_U : S++ // <foo bar="
, CLOSE_TAG : S++ // </a
, CLOSE_TAG_SAW_WHITE : S++ // </a >
, SCRIPT : S++ // <script> ...
, SCRIPT_ENDING : S++ // <script> ... <
}
sax.ENTITIES =
{ "apos" : "'"
, "quot" : "\""
, "amp" : "&"
, "gt" : ">"
, "lt" : "<"
}
for (var S in sax.STATE) sax.STATE[sax.STATE[S]] = S
// shorthand
S = sax.STATE
function emit (parser, event, data) {
parser[event] && parser[event](data)
}
function emitNode (parser, nodeType, data) {
if (parser.textNode) closeText(parser)
emit(parser, nodeType, data)
}
function closeText (parser) {
parser.textNode = textopts(parser.opt, parser.textNode)
if (parser.textNode) emit(parser, "ontext", parser.textNode)
parser.textNode = ""
}
function textopts (opt, text) {
if (opt.trim) text = text.trim()
if (opt.normalize) text = text.replace(/\s+/g, " ")
return text
}
function error (parser, er) {
closeText(parser)
er += "\nLine: "+parser.line+
"\nColumn: "+parser.column+
"\nChar: "+parser.c
er = new Error(er)
parser.error = er
emit(parser, "onerror", er)
return parser
}
function end (parser) {
if (parser.state !== S.TEXT) error(parser, "Unexpected end")
closeText(parser)
parser.c = ""
parser.closed = true
emit(parser, "onend")
SAXParser.call(parser, parser.strict, parser.opt)
return parser
}
function strictFail (parser, message) {
if (parser.strict) error(parser, message)
}
function newTag (parser) {
if (!parser.strict) parser.tagName = parser.tagName[parser.tagCase]()
var parent = parser.tags[parser.tags.length - 1] || parser
, tag = parser.tag = { name : parser.tagName, attributes : {} }
// will be overridden if tag contails an xmlns="foo" or xmlns:foo="bar"
if (parser.opt.xmlns) tag.ns = parent.ns
parser.attribList.length = 0
}
function qname (name) {
var i = name.indexOf(":")
, qualName = i < 0 ? [ "", name ] : name.split(":")
, prefix = qualName[0]
, local = qualName[1]
// <x "xmlns"="http://foo">
if (name === "xmlns") {
prefix = "xmlns"
local = ""
}
return { prefix: prefix, local: local }
}
function attrib (parser) {
if (parser.opt.xmlns) {
var qn = qname(parser.attribName)
, prefix = qn.prefix
, local = qn.local
if (prefix === "xmlns") {
// namespace binding attribute; push the binding into scope
if (local === "xml" && parser.attribValue !== XML_NAMESPACE) {
strictFail( parser
, "xml: prefix must be bound to " + XML_NAMESPACE + "\n"
+ "Actual: " + parser.attribValue )
} else if (local === "xmlns" && parser.attribValue !== XMLNS_NAMESPACE) {
strictFail( parser
, "xmlns: prefix must be bound to " + XMLNS_NAMESPACE + "\n"
+ "Actual: " + parser.attribValue )
} else {
var tag = parser.tag
, parent = parser.tags[parser.tags.length - 1] || parser
if (tag.ns === parent.ns) {
tag.ns = Object.create(parent.ns)
}
tag.ns[local] = parser.attribValue
}
}
// defer onattribute events until all attributes have been seen
// so any new bindings can take effect; preserve attribute order
// so deferred events can be emitted in document order
parser.attribList.push([parser.attribName, parser.attribValue])
} else {
// in non-xmlns mode, we can emit the event right away
parser.tag.attributes[parser.attribName] = parser.attribValue
emitNode( parser
, "onattribute"
, { name: parser.attribName
, value: parser.attribValue } )
}
parser.attribName = parser.attribValue = ""
}
function openTag (parser, selfClosing) {
if (parser.opt.xmlns) {
// emit namespace binding events
var tag = parser.tag
// add namespace info to tag
var qn = qname(parser.tagName)
tag.prefix = qn.prefix
tag.local = qn.local
tag.uri = tag.ns[qn.prefix] || qn.prefix
if (tag.prefix && !tag.uri) {
strictFail(parser, "Unbound namespace prefix: "
+ JSON.stringify(parser.tagName))
}
var parent = parser.tags[parser.tags.length - 1] || parser
if (tag.ns && parent.ns !== tag.ns) {
Object.keys(tag.ns).forEach(function (p) {
emitNode( parser
, "onopennamespace"
, { prefix: p , uri: tag.ns[p] } )
})
}
// handle deferred onattribute events
for (var i = 0, l = parser.attribList.length; i < l; i ++) {
var nv = parser.attribList[i]
var name = nv[0]
, value = nv[1]
, qualName = qname(name)
, prefix = qualName.prefix
, local = qualName.local
, uri = tag.ns[prefix] || ""
, a = { name: name
, value: value
, prefix: prefix
, local: local
, uri: uri
}
// if there's any attributes with an undefined namespace,
// then fail on them now.
if (prefix && prefix != "xmlns" && !uri) {
strictFail(parser, "Unbound namespace prefix: "
+ JSON.stringify(prefix))
a.uri = prefix
}
parser.tag.attributes[name] = a
emitNode(parser, "onattribute", a)
}
parser.attribList.length = 0
}
// process the tag
parser.sawRoot = true
parser.tags.push(parser.tag)
emitNode(parser, "onopentag", parser.tag)
if (!selfClosing) {
// special case for <script> in non-strict mode.
if (!parser.noscript && parser.tagName.toLowerCase() === "script") {
parser.state = S.SCRIPT
} else {
parser.state = S.TEXT
}
parser.tag = null
parser.tagName = ""
}
parser.attribName = parser.attribValue = ""
parser.attribList.length = 0
}
function closeTag (parser) {
if (!parser.tagName) {
strictFail(parser, "Weird empty close tag.")
parser.textNode += "</>"
parser.state = S.TEXT
return
}
// first make sure that the closing tag actually exists.
// <a><b></c></b></a> will close everything, otherwise.
var t = parser.tags.length
var tagName = parser.tagName
if (!parser.strict) tagName = tagName[parser.tagCase]()
var closeTo = tagName
while (t --) {
var close = parser.tags[t]
if (close.name !== closeTo) {
// fail the first time in strict mode
strictFail(parser, "Unexpected close tag")
} else break
}
// didn't find it. we already failed for strict, so just abort.
if (t < 0) {
strictFail(parser, "Unmatched closing tag: "+parser.tagName)
parser.textNode += "</" + parser.tagName + ">"
parser.state = S.TEXT
return
}
parser.tagName = tagName
var s = parser.tags.length
while (s --> t) {
var tag = parser.tag = parser.tags.pop()
parser.tagName = parser.tag.name
emitNode(parser, "onclosetag", parser.tagName)
var x = {}
for (var i in tag.ns) x[i] = tag.ns[i]
var parent = parser.tags[parser.tags.length - 1] || parser
if (parser.opt.xmlns && tag.ns !== parent.ns) {
// remove namespace bindings introduced by tag
Object.keys(tag.ns).forEach(function (p) {
var n = tag.ns[p]
emitNode(parser, "onclosenamespace", { prefix: p, uri: n })
})
}
}
if (t === 0) parser.closedRoot = true
parser.tagName = parser.attribValue = parser.attribName = ""
parser.attribList.length = 0
parser.state = S.TEXT
}
function parseEntity (parser) {
var entity = parser.entity.toLowerCase()
, num
, numStr = ""
if (parser.ENTITIES[entity]) return parser.ENTITIES[entity]
if (entity.charAt(0) === "#") {
if (entity.charAt(1) === "x") {
entity = entity.slice(2)
num = parseInt(entity, 16)
numStr = num.toString(16)
} else {
entity = entity.slice(1)
num = parseInt(entity, 10)
numStr = num.toString(10)
}
}
entity = entity.replace(/^0+/, "")
if (numStr.toLowerCase() !== entity) {
strictFail(parser, "Invalid character entity")
return "&"+parser.entity + ";"
}
return String.fromCharCode(num)
}
function write (chunk) {
var parser = this
if (this.error) throw this.error
if (parser.closed) return error(parser,
"Cannot write after close. Assign an onready handler.")
if (chunk === null) return end(parser)
var i = 0, c = ""
while (parser.c = c = chunk.charAt(i++)) {
parser.position ++
if (c === "\n") {
parser.line ++
parser.column = 0
} else parser.column ++
switch (parser.state) {
case S.BEGIN:
if (c === "<") parser.state = S.OPEN_WAKA
else if (not(whitespace,c)) {
// have to process this as a text node.
// weird, but happens.
strictFail(parser, "Non-whitespace before first tag.")
parser.textNode = c
parser.state = S.TEXT
}
continue
case S.TEXT:
if (parser.sawRoot && !parser.closedRoot) {
var starti = i-1
while (c && c!=="<" && c!=="&") {
c = chunk.charAt(i++)
if (c) {
parser.position ++
if (c === "\n") {
parser.line ++
parser.column = 0
} else parser.column ++
}
}
parser.textNode += chunk.substring(starti, i-1)
}
if (c === "<") parser.state = S.OPEN_WAKA
else {
if (not(whitespace, c) && (!parser.sawRoot || parser.closedRoot))
strictFail("Text data outside of root node.")
if (c === "&") parser.state = S.TEXT_ENTITY
else parser.textNode += c
}
continue
case S.SCRIPT:
// only non-strict
if (c === "<") {
parser.state = S.SCRIPT_ENDING
} else parser.script += c
continue
case S.SCRIPT_ENDING:
if (c === "/") {
emitNode(parser, "onscript", parser.script)
parser.state = S.CLOSE_TAG
parser.script = ""
parser.tagName = ""
} else {
parser.script += "<" + c
parser.state = S.SCRIPT
}
continue
case S.OPEN_WAKA:
// either a /, ?, !, or text is coming next.
if (c === "!") {
parser.state = S.SGML_DECL
parser.sgmlDecl = ""
} else if (is(whitespace, c)) {
// wait for it...
} else if (is(nameStart,c)) {
parser.startTagPosition = parser.position - 1
parser.state = S.OPEN_TAG
parser.tagName = c
} else if (c === "/") {
parser.startTagPosition = parser.position - 1
parser.state = S.CLOSE_TAG
parser.tagName = ""
} else if (c === "?") {
parser.state = S.PROC_INST
parser.procInstName = parser.procInstBody = ""
} else {
strictFail(parser, "Unencoded <")
parser.textNode += "<" + c
parser.state = S.TEXT
}
continue
case S.SGML_DECL:
if ((parser.sgmlDecl+c).toUpperCase() === CDATA) {
emitNode(parser, "onopencdata")
parser.state = S.CDATA
parser.sgmlDecl = ""
parser.cdata = ""
} else if (parser.sgmlDecl+c === "--") {
parser.state = S.COMMENT
parser.comment = ""
parser.sgmlDecl = ""
} else if ((parser.sgmlDecl+c).toUpperCase() === DOCTYPE) {
parser.state = S.DOCTYPE
if (parser.doctype || parser.sawRoot) strictFail(parser,
"Inappropriately located doctype declaration")
parser.doctype = ""
parser.sgmlDecl = ""
} else if (c === ">") {
emitNode(parser, "onsgmldeclaration", parser.sgmlDecl)
parser.sgmlDecl = ""
parser.state = S.TEXT
} else if (is(quote, c)) {
parser.state = S.SGML_DECL_QUOTED
parser.sgmlDecl += c
} else parser.sgmlDecl += c
continue
case S.SGML_DECL_QUOTED:
if (c === parser.q) {
parser.state = S.SGML_DECL
parser.q = ""
}
parser.sgmlDecl += c
continue
case S.DOCTYPE:
if (c === ">") {
parser.state = S.TEXT
emitNode(parser, "ondoctype", parser.doctype)
parser.doctype = true // just remember that we saw it.
} else {
parser.doctype += c
if (c === "[") parser.state = S.DOCTYPE_DTD
else if (is(quote, c)) {
parser.state = S.DOCTYPE_QUOTED
parser.q = c
}
}
continue
case S.DOCTYPE_QUOTED:
parser.doctype += c
if (c === parser.q) {
parser.q = ""
parser.state = S.DOCTYPE
}
continue
case S.DOCTYPE_DTD:
parser.doctype += c
if (c === "]") parser.state = S.DOCTYPE
else if (is(quote,c)) {
parser.state = S.DOCTYPE_DTD_QUOTED
parser.q = c
}
continue
case S.DOCTYPE_DTD_QUOTED:
parser.doctype += c
if (c === parser.q) {
parser.state = S.DOCTYPE_DTD
parser.q = ""
}
continue
case S.COMMENT:
if (c === "-") parser.state = S.COMMENT_ENDING
else parser.comment += c
continue
case S.COMMENT_ENDING:
if (c === "-") {
parser.state = S.COMMENT_ENDED
parser.comment = textopts(parser.opt, parser.comment)
if (parser.comment) emitNode(parser, "oncomment", parser.comment)
parser.comment = ""
} else {
parser.comment += "-" + c
parser.state = S.COMMENT
}
continue
case S.COMMENT_ENDED:
if (c !== ">") {
strictFail(parser, "Malformed comment")
// allow <!-- blah -- bloo --> in non-strict mode,
// which is a comment of " blah -- bloo "
parser.comment += "--" + c
parser.state = S.COMMENT
} else parser.state = S.TEXT
continue
case S.CDATA:
if (c === "]") parser.state = S.CDATA_ENDING
else parser.cdata += c
continue
case S.CDATA_ENDING:
if (c === "]") parser.state = S.CDATA_ENDING_2
else {
parser.cdata += "]" + c
parser.state = S.CDATA
}
continue
case S.CDATA_ENDING_2:
if (c === ">") {
if (parser.cdata) emitNode(parser, "oncdata", parser.cdata)
emitNode(parser, "onclosecdata")
parser.cdata = ""
parser.state = S.TEXT
} else if (c === "]") {
parser.cdata += "]"
} else {
parser.cdata += "]]" + c
parser.state = S.CDATA
}
continue
case S.PROC_INST:
if (c === "?") parser.state = S.PROC_INST_ENDING
else if (is(whitespace, c)) parser.state = S.PROC_INST_BODY
else parser.procInstName += c
continue
case S.PROC_INST_BODY:
if (!parser.procInstBody && is(whitespace, c)) continue
else if (c === "?") parser.state = S.PROC_INST_ENDING
else if (is(quote, c)) {
parser.state = S.PROC_INST_QUOTED
parser.q = c
parser.procInstBody += c
} else parser.procInstBody += c
continue
case S.PROC_INST_ENDING:
if (c === ">") {
emitNode(parser, "onprocessinginstruction", {
name : parser.procInstName,
body : parser.procInstBody
})
parser.procInstName = parser.procInstBody = ""
parser.state = S.TEXT
} else {
parser.procInstBody += "?" + c
parser.state = S.PROC_INST_BODY
}
continue
case S.PROC_INST_QUOTED:
parser.procInstBody += c
if (c === parser.q) {
parser.state = S.PROC_INST_BODY
parser.q = ""
}
continue
case S.OPEN_TAG:
if (is(nameBody, c)) parser.tagName += c
else {
newTag(parser)
if (c === ">") openTag(parser)
else if (c === "/") parser.state = S.OPEN_TAG_SLASH
else {
if (not(whitespace, c)) strictFail(
parser, "Invalid character in tag name")
parser.state = S.ATTRIB
}
}
continue
case S.OPEN_TAG_SLASH:
if (c === ">") {
openTag(parser, true)
closeTag(parser)
} else {
strictFail(parser, "Forward-slash in opening tag not followed by >")
parser.state = S.ATTRIB
}
continue
case S.ATTRIB:
// haven't read the attribute name yet.
if (is(whitespace, c)) continue
else if (c === ">") openTag(parser)
else if (c === "/") parser.state = S.OPEN_TAG_SLASH
else if (is(nameStart, c)) {
parser.attribName = c
parser.attribValue = ""
parser.state = S.ATTRIB_NAME
} else strictFail(parser, "Invalid attribute name")
continue
case S.ATTRIB_NAME:
if (c === "=") parser.state = S.ATTRIB_VALUE
else if (is(whitespace, c)) parser.state = S.ATTRIB_NAME_SAW_WHITE
else if (is(nameBody, c)) parser.attribName += c
else strictFail(parser, "Invalid attribute name")
continue
case S.ATTRIB_NAME_SAW_WHITE:
if (c === "=") parser.state = S.ATTRIB_VALUE
else if (is(whitespace, c)) continue
else {
strictFail(parser, "Attribute without value")
parser.tag.attributes[parser.attribName] = ""
parser.attribValue = ""
emitNode(parser, "onattribute",
{ name : parser.attribName, value : "" })
parser.attribName = ""
if (c === ">") openTag(parser)
else if (is(nameStart, c)) {
parser.attribName = c
parser.state = S.ATTRIB_NAME
} else {
strictFail(parser, "Invalid attribute name")
parser.state = S.ATTRIB
}
}
continue
case S.ATTRIB_VALUE:
if (is(whitespace, c)) continue
else if (is(quote, c)) {
parser.q = c
parser.state = S.ATTRIB_VALUE_QUOTED
} else {
strictFail(parser, "Unquoted attribute value")
parser.state = S.ATTRIB_VALUE_UNQUOTED
parser.attribValue = c
}
continue
case S.ATTRIB_VALUE_QUOTED:
if (c !== parser.q) {
if (c === "&") parser.state = S.ATTRIB_VALUE_ENTITY_Q
else parser.attribValue += c
continue
}
attrib(parser)
parser.q = ""
parser.state = S.ATTRIB
continue
case S.ATTRIB_VALUE_UNQUOTED:
if (not(attribEnd,c)) {
if (c === "&") parser.state = S.ATTRIB_VALUE_ENTITY_U
else parser.attribValue += c
continue
}
attrib(parser)
if (c === ">") openTag(parser)
else parser.state = S.ATTRIB
continue
case S.CLOSE_TAG:
if (!parser.tagName) {
if (is(whitespace, c)) continue
else if (not(nameStart, c)) strictFail(parser,
"Invalid tagname in closing tag.")
else parser.tagName = c
}
else if (c === ">") closeTag(parser)
else if (is(nameBody, c)) parser.tagName += c
else {
if (not(whitespace, c)) strictFail(parser,
"Invalid tagname in closing tag")
parser.state = S.CLOSE_TAG_SAW_WHITE
}
continue
case S.CLOSE_TAG_SAW_WHITE:
if (is(whitespace, c)) continue
if (c === ">") closeTag(parser)
else strictFail("Invalid characters in closing tag")
continue
case S.TEXT_ENTITY:
case S.ATTRIB_VALUE_ENTITY_Q:
case S.ATTRIB_VALUE_ENTITY_U:
switch(parser.state) {
case S.TEXT_ENTITY:
var returnState = S.TEXT, buffer = "textNode"
break
case S.ATTRIB_VALUE_ENTITY_Q:
var returnState = S.ATTRIB_VALUE_QUOTED, buffer = "attribValue"
break
case S.ATTRIB_VALUE_ENTITY_U:
var returnState = S.ATTRIB_VALUE_UNQUOTED, buffer = "attribValue"
break
}
if (c === ";") {
parser[buffer] += parseEntity(parser)
parser.entity = ""
parser.state = returnState
}
else if (is(entity, c)) parser.entity += c
else {
strictFail("Invalid character entity")
parser[buffer] += "&" + parser.entity + c
parser.entity = ""
parser.state = returnState
}
continue
default:
throw new Error(parser, "Unknown state: " + parser.state)
}
} // while
// cdata blocks can get very big under normal conditions. emit and move on.
// if (parser.state === S.CDATA && parser.cdata) {
// emitNode(parser, "oncdata", parser.cdata)
// parser.cdata = ""
// }
if (parser.position >= parser.bufferCheckPosition) checkBufferLength(parser)
return parser
}
})(typeof exports === "undefined" ? sax = {} : exports)
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| q.js | 28.19% | (221 / 784) | 9.29% | (25 / 269) | 3.6% | (8 / 222) | 28.26% | (221 / 782) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 6 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | // vim:ts=4:sts=4:sw=4:
/*!
*
* Copyright 2009-2012 Kris Kowal under the terms of the MIT
* license found at http://github.com/kriskowal/q/raw/master/LICENSE
*
* With parts by Tyler Close
* Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
* at http://www.opensource.org/licenses/mit-license.html
* Forked at ref_send.js version: 2009-05-11
*
* With parts by Mark Miller
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
(function (definition) {
"use strict";
// This file will function properly as a <script> tag, or a module
// using CommonJS and NodeJS or RequireJS module formats. In
// Common/Node/RequireJS, the module exports the Q API and when
// executed as a simple <script>, it creates a Q global instead.
// Montage Require
Iif (typeof bootstrap === "function") {
bootstrap("promise", definition);
// CommonJS
} else Eif (typeof exports === "object" && typeof module === "object") {
module.exports = definition();
// RequireJS
} else if (typeof define === "function" && define.amd) {
define(definition);
// SES (Secure EcmaScript)
} else if (typeof ses !== "undefined") {
if (!ses.ok()) {
return;
} else {
ses.makeQ = definition;
}
// <script>
} else if (typeof window !== "undefined" || typeof self !== "undefined") {
// Prefer window over self for add-on scripts. Use self for
// non-windowed contexts.
var global = typeof window !== "undefined" ? window : self;
// Get the `window` object, save the previous Q global
// and initialize Q as a global.
var previousQ = global.Q;
global.Q = definition();
// Add a noConflict function so Q can be removed from the
// global namespace.
global.Q.noConflict = function () {
global.Q = previousQ;
return this;
};
} else {
throw new Error("This environment was not anticipated by Q. Please file a bug.");
}
})(function () {
"use strict";
var hasStacks = false;
try {
throw new Error();
} catch (e) {
hasStacks = !!e.stack;
}
// All code after this point will be filtered from stack traces reported
// by Q.
var qStartingLine = captureLine();
var qFileName;
// shims
// used for fallback in "allResolved"
var noop = function () {};
// Use the fastest possible means to execute a task in a future turn
// of the event loop.
var nextTick =(function () {
// linked list of tasks (single, with head node)
var head = {task: void 0, next: null};
var tail = head;
var flushing = false;
var requestTick = void 0;
var isNodeJS = false;
// queue for late tasks, used by unhandled rejection tracking
var laterQueue = [];
function flush() {
/* jshint loopfunc: true */
var task, domain;
while (head.next) {
head = head.next;
task = head.task;
head.task = void 0;
domain = head.domain;
if (domain) {
head.domain = void 0;
domain.enter();
}
runSingle(task, domain);
}
while (laterQueue.length) {
task = laterQueue.pop();
runSingle(task);
}
flushing = false;
}
// runs a single function in the async queue
function runSingle(task, domain) {
try {
task();
} catch (e) {
if (isNodeJS) {
// In node, uncaught exceptions are considered fatal errors.
// Re-throw them synchronously to interrupt flushing!
// Ensure continuation if the uncaught exception is suppressed
// listening "uncaughtException" events (as domains does).
// Continue in next event to avoid tick recursion.
if (domain) {
domain.exit();
}
setTimeout(flush, 0);
if (domain) {
domain.enter();
}
throw e;
} else {
// In browsers, uncaught exceptions are not fatal.
// Re-throw them asynchronously to avoid slow-downs.
setTimeout(function () {
throw e;
}, 0);
}
}
if (domain) {
domain.exit();
}
}
nextTick = function (task) {
tail = tail.next = {
task: task,
domain: isNodeJS && process.domain,
next: null
};
if (!flushing) {
flushing = true;
requestTick();
}
};
Eif (typeof process === "object" &&
process.toString() === "[object process]" && process.nextTick) {
// Ensure Q is in a real Node environment, with a `process.nextTick`.
// To see through fake Node environments:
// * Mocha test runner - exposes a `process` global without a `nextTick`
// * Browserify - exposes a `process.nexTick` function that uses
// `setTimeout`. In this case `setImmediate` is preferred because
// it is faster. Browserify's `process.toString()` yields
// "[object Object]", while in a real Node environment
// `process.nextTick()` yields "[object process]".
isNodeJS = true;
requestTick = function () {
process.nextTick(flush);
};
} else if (typeof setImmediate === "function") {
// In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
if (typeof window !== "undefined") {
requestTick = setImmediate.bind(window, flush);
} else {
requestTick = function () {
setImmediate(flush);
};
}
} else if (typeof MessageChannel !== "undefined") {
// modern browsers
// http://www.nonblocking.io/2011/06/windownexttick.html
var channel = new MessageChannel();
// At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
// working message ports the first time a page loads.
channel.port1.onmessage = function () {
requestTick = requestPortTick;
channel.port1.onmessage = flush;
flush();
};
var requestPortTick = function () {
// Opera requires us to provide a message payload, regardless of
// whether we use it.
channel.port2.postMessage(0);
};
requestTick = function () {
setTimeout(flush, 0);
requestPortTick();
};
} else {
// old browsers
requestTick = function () {
setTimeout(flush, 0);
};
}
// runs a task after all other tasks have been run
// this is useful for unhandled rejection tracking that needs to happen
// after all `then`d tasks have been run.
nextTick.runAfter = function (task) {
laterQueue.push(task);
if (!flushing) {
flushing = true;
requestTick();
}
};
return nextTick;
})();
// Attempt to make generics safe in the face of downstream
// modifications.
// There is no situation where this is necessary.
// If you need a security guarantee, these primordials need to be
// deeply frozen anyway, and if you don’t need a security guarantee,
// this is just plain paranoid.
// However, this **might** have the nice side-effect of reducing the size of
// the minified code by reducing x.call() to merely x()
// See Mark Miller’s explanation of what this does.
// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
var call = Function.call;
function uncurryThis(f) {
return function () {
return call.apply(f, arguments);
};
}
// This is equivalent, but slower:
// uncurryThis = Function_bind.bind(Function_bind.call);
// http://jsperf.com/uncurrythis
var array_slice = uncurryThis(Array.prototype.slice);
var array_reduce = uncurryThis(
Array.prototype.reduce || function (callback, basis) {
var index = 0,
length = this.length;
// concerning the initial value, if one is not provided
if (arguments.length === 1) {
// seek to the first value in the array, accounting
// for the possibility that is is a sparse array
do {
if (index in this) {
basis = this[index++];
break;
}
if (++index >= length) {
throw new TypeError();
}
} while (1);
}
// reduce
for (; index < length; index++) {
// account for the possibility that the array is sparse
if (index in this) {
basis = callback(basis, this[index], index);
}
}
return basis;
}
);
var array_indexOf = uncurryThis(
Array.prototype.indexOf || function (value) {
// not a very good shim, but good enough for our one use of it
for (var i = 0; i < this.length; i++) {
if (this[i] === value) {
return i;
}
}
return -1;
}
);
var array_map = uncurryThis(
Array.prototype.map || function (callback, thisp) {
var self = this;
var collect = [];
array_reduce(self, function (undefined, value, index) {
collect.push(callback.call(thisp, value, index, self));
}, void 0);
return collect;
}
);
var object_create = Object.create || function (prototype) {
function Type() { }
Type.prototype = prototype;
return new Type();
};
var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
var object_keys = Object.keys || function (object) {
var keys = [];
for (var key in object) {
if (object_hasOwnProperty(object, key)) {
keys.push(key);
}
}
return keys;
};
var object_toString = uncurryThis(Object.prototype.toString);
function isObject(value) {
return value === Object(value);
}
// generator related shims
// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
function isStopIteration(exception) {
return (
object_toString(exception) === "[object StopIteration]" ||
exception instanceof QReturnValue
);
}
// FIXME: Remove this helper and Q.return once ES6 generators are in
// SpiderMonkey.
var QReturnValue;
Iif (typeof ReturnValue !== "undefined") {
QReturnValue = ReturnValue;
} else {
QReturnValue = function (value) {
this.value = value;
};
}
// long stack traces
var STACK_JUMP_SEPARATOR = "From previous event:";
function makeStackTraceLong(error, promise) {
// If possible, transform the error stack trace by removing Node and Q
// cruft, then concatenating with the stack trace of `promise`. See #57.
if (hasStacks &&
promise.stack &&
typeof error === "object" &&
error !== null &&
error.stack &&
error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
) {
var stacks = [];
for (var p = promise; !!p; p = p.source) {
if (p.stack) {
stacks.unshift(p.stack);
}
}
stacks.unshift(error.stack);
var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
error.stack = filterStackString(concatedStacks);
}
}
function filterStackString(stackString) {
var lines = stackString.split("\n");
var desiredLines = [];
for (var i = 0; i < lines.length; ++i) {
var line = lines[i];
if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
desiredLines.push(line);
}
}
return desiredLines.join("\n");
}
function isNodeFrame(stackLine) {
return stackLine.indexOf("(module.js:") !== -1 ||
stackLine.indexOf("(node.js:") !== -1;
}
function getFileNameAndLineNumber(stackLine) {
// Named functions: "at functionName (filename:lineNumber:columnNumber)"
// In IE10 function name can have spaces ("Anonymous function") O_o
var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
Iif (attempt1) {
return [attempt1[1], Number(attempt1[2])];
}
// Anonymous functions: "at filename:lineNumber:columnNumber"
var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
Eif (attempt2) {
return [attempt2[1], Number(attempt2[2])];
}
// Firefox style: "function@filename:lineNumber or @filename:lineNumber"
var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
if (attempt3) {
return [attempt3[1], Number(attempt3[2])];
}
}
function isInternalFrame(stackLine) {
var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
if (!fileNameAndLineNumber) {
return false;
}
var fileName = fileNameAndLineNumber[0];
var lineNumber = fileNameAndLineNumber[1];
return fileName === qFileName &&
lineNumber >= qStartingLine &&
lineNumber <= qEndingLine;
}
// discover own file name and line number range for filtering stack
// traces
function captureLine() {
Iif (!hasStacks) {
return;
}
try {
throw new Error();
} catch (e) {
var lines = e.stack.split("\n");
var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
Iif (!fileNameAndLineNumber) {
return;
}
qFileName = fileNameAndLineNumber[0];
return fileNameAndLineNumber[1];
}
}
function deprecate(callback, name, alternative) {
return function () {
if (typeof console !== "undefined" &&
typeof console.warn === "function") {
console.warn(name + " is deprecated, use " + alternative +
" instead.", new Error("").stack);
}
return callback.apply(callback, arguments);
};
}
// end of shims
// beginning of real work
/**
* Constructs a promise for an immediate reference, passes promises through, or
* coerces promises from different systems.
* @param value immediate reference or promise
*/
function Q(value) {
// If the object is already a Promise, return it directly. This enables
// the resolve function to both be used to created references from objects,
// but to tolerably coerce non-promises to promises.
if (value instanceof Promise) {
return value;
}
// assimilate thenables
if (isPromiseAlike(value)) {
return coerce(value);
} else {
return fulfill(value);
}
}
Q.resolve = Q;
/**
* Performs a task in a future turn of the event loop.
* @param {Function} task
*/
Q.nextTick = nextTick;
/**
* Controls whether or not long stack traces will be on
*/
Q.longStackSupport = false;
// enable long stacks if Q_DEBUG is set
Iif (typeof process === "object" && process && process.env && process.env.Q_DEBUG) {
Q.longStackSupport = true;
}
/**
* Constructs a {promise, resolve, reject} object.
*
* `resolve` is a callback to invoke with a more resolved value for the
* promise. To fulfill the promise, invoke `resolve` with any value that is
* not a thenable. To reject the promise, invoke `resolve` with a rejected
* thenable, or invoke `reject` with the reason directly. To resolve the
* promise to another thenable, thus putting it in the same state, invoke
* `resolve` with that other thenable.
*/
Q.defer = defer;
function defer() {
// if "messages" is an "Array", that indicates that the promise has not yet
// been resolved. If it is "undefined", it has been resolved. Each
// element of the messages array is itself an array of complete arguments to
// forward to the resolved promise. We coerce the resolution value to a
// promise using the `resolve` function because it handles both fully
// non-thenable values and other thenables gracefully.
var messages = [], progressListeners = [], resolvedPromise;
var deferred = object_create(defer.prototype);
var promise = object_create(Promise.prototype);
promise.promiseDispatch = function (resolve, op, operands) {
var args = array_slice(arguments);
if (messages) {
messages.push(args);
if (op === "when" && operands[1]) { // progress operand
progressListeners.push(operands[1]);
}
} else {
Q.nextTick(function () {
resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
});
}
};
// XXX deprecated
promise.valueOf = function () {
if (messages) {
return promise;
}
var nearerValue = nearer(resolvedPromise);
if (isPromise(nearerValue)) {
resolvedPromise = nearerValue; // shorten chain
}
return nearerValue;
};
promise.inspect = function () {
if (!resolvedPromise) {
return { state: "pending" };
}
return resolvedPromise.inspect();
};
if (Q.longStackSupport && hasStacks) {
try {
throw new Error();
} catch (e) {
// NOTE: don't try to use `Error.captureStackTrace` or transfer the
// accessor around; that causes memory leaks as per GH-111. Just
// reify the stack trace as a string ASAP.
//
// At the same time, cut off the first line; it's always just
// "[object Promise]\n", as per the `toString`.
promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
}
}
// NOTE: we do the checks for `resolvedPromise` in each method, instead of
// consolidating them into `become`, since otherwise we'd create new
// promises with the lines `become(whatever(value))`. See e.g. GH-252.
function become(newPromise) {
resolvedPromise = newPromise;
promise.source = newPromise;
array_reduce(messages, function (undefined, message) {
Q.nextTick(function () {
newPromise.promiseDispatch.apply(newPromise, message);
});
}, void 0);
messages = void 0;
progressListeners = void 0;
}
deferred.promise = promise;
deferred.resolve = function (value) {
if (resolvedPromise) {
return;
}
become(Q(value));
};
deferred.fulfill = function (value) {
if (resolvedPromise) {
return;
}
become(fulfill(value));
};
deferred.reject = function (reason) {
if (resolvedPromise) {
return;
}
become(reject(reason));
};
deferred.notify = function (progress) {
if (resolvedPromise) {
return;
}
array_reduce(progressListeners, function (undefined, progressListener) {
Q.nextTick(function () {
progressListener(progress);
});
}, void 0);
};
return deferred;
}
/**
* Creates a Node-style callback that will resolve or reject the deferred
* promise.
* @returns a nodeback
*/
defer.prototype.makeNodeResolver = function () {
var self = this;
return function (error, value) {
if (error) {
self.reject(error);
} else if (arguments.length > 2) {
self.resolve(array_slice(arguments, 1));
} else {
self.resolve(value);
}
};
};
/**
* @param resolver {Function} a function that returns nothing and accepts
* the resolve, reject, and notify functions for a deferred.
* @returns a promise that may be resolved with the given resolve and reject
* functions, or rejected by a thrown exception in resolver
*/
Q.Promise = promise; // ES6
Q.promise = promise;
function promise(resolver) {
if (typeof resolver !== "function") {
throw new TypeError("resolver must be a function.");
}
var deferred = defer();
try {
resolver(deferred.resolve, deferred.reject, deferred.notify);
} catch (reason) {
deferred.reject(reason);
}
return deferred.promise;
}
promise.race = race; // ES6
promise.all = all; // ES6
promise.reject = reject; // ES6
promise.resolve = Q; // ES6
// XXX experimental. This method is a way to denote that a local value is
// serializable and should be immediately dispatched to a remote upon request,
// instead of passing a reference.
Q.passByCopy = function (object) {
//freeze(object);
//passByCopies.set(object, true);
return object;
};
Promise.prototype.passByCopy = function () {
//freeze(object);
//passByCopies.set(object, true);
return this;
};
/**
* If two promises eventually fulfill to the same value, promises that value,
* but otherwise rejects.
* @param x {Any*}
* @param y {Any*}
* @returns {Any*} a promise for x and y if they are the same, but a rejection
* otherwise.
*
*/
Q.join = function (x, y) {
return Q(x).join(y);
};
Promise.prototype.join = function (that) {
return Q([this, that]).spread(function (x, y) {
if (x === y) {
// TODO: "===" should be Object.is or equiv
return x;
} else {
throw new Error("Can't join: not the same: " + x + " " + y);
}
});
};
/**
* Returns a promise for the first of an array of promises to become settled.
* @param answers {Array[Any*]} promises to race
* @returns {Any*} the first promise to be settled
*/
Q.race = race;
function race(answerPs) {
return promise(function (resolve, reject) {
// Switch to this once we can assume at least ES5
// answerPs.forEach(function (answerP) {
// Q(answerP).then(resolve, reject);
// });
// Use this in the meantime
for (var i = 0, len = answerPs.length; i < len; i++) {
Q(answerPs[i]).then(resolve, reject);
}
});
}
Promise.prototype.race = function () {
return this.then(Q.race);
};
/**
* Constructs a Promise with a promise descriptor object and optional fallback
* function. The descriptor contains methods like when(rejected), get(name),
* set(name, value), post(name, args), and delete(name), which all
* return either a value, a promise for a value, or a rejection. The fallback
* accepts the operation name, a resolver, and any further arguments that would
* have been forwarded to the appropriate method above had a method been
* provided with the proper name. The API makes no guarantees about the nature
* of the returned object, apart from that it is usable whereever promises are
* bought and sold.
*/
Q.makePromise = Promise;
function Promise(descriptor, fallback, inspect) {
if (fallback === void 0) {
fallback = function (op) {
return reject(new Error(
"Promise does not support operation: " + op
));
};
}
if (inspect === void 0) {
inspect = function () {
return {state: "unknown"};
};
}
var promise = object_create(Promise.prototype);
promise.promiseDispatch = function (resolve, op, args) {
var result;
try {
if (descriptor[op]) {
result = descriptor[op].apply(promise, args);
} else {
result = fallback.call(promise, op, args);
}
} catch (exception) {
result = reject(exception);
}
if (resolve) {
resolve(result);
}
};
promise.inspect = inspect;
// XXX deprecated `valueOf` and `exception` support
if (inspect) {
var inspected = inspect();
if (inspected.state === "rejected") {
promise.exception = inspected.reason;
}
promise.valueOf = function () {
var inspected = inspect();
if (inspected.state === "pending" ||
inspected.state === "rejected") {
return promise;
}
return inspected.value;
};
}
return promise;
}
Promise.prototype.toString = function () {
return "[object Promise]";
};
Promise.prototype.then = function (fulfilled, rejected, progressed) {
var self = this;
var deferred = defer();
var done = false; // ensure the untrusted promise makes at most a
// single call to one of the callbacks
function _fulfilled(value) {
try {
return typeof fulfilled === "function" ? fulfilled(value) : value;
} catch (exception) {
return reject(exception);
}
}
function _rejected(exception) {
if (typeof rejected === "function") {
makeStackTraceLong(exception, self);
try {
return rejected(exception);
} catch (newException) {
return reject(newException);
}
}
return reject(exception);
}
function _progressed(value) {
return typeof progressed === "function" ? progressed(value) : value;
}
Q.nextTick(function () {
self.promiseDispatch(function (value) {
if (done) {
return;
}
done = true;
deferred.resolve(_fulfilled(value));
}, "when", [function (exception) {
if (done) {
return;
}
done = true;
deferred.resolve(_rejected(exception));
}]);
});
// Progress propagator need to be attached in the current tick.
self.promiseDispatch(void 0, "when", [void 0, function (value) {
var newValue;
var threw = false;
try {
newValue = _progressed(value);
} catch (e) {
threw = true;
if (Q.onerror) {
Q.onerror(e);
} else {
throw e;
}
}
if (!threw) {
deferred.notify(newValue);
}
}]);
return deferred.promise;
};
Q.tap = function (promise, callback) {
return Q(promise).tap(callback);
};
/**
* Works almost like "finally", but not called for rejections.
* Original resolution value is passed through callback unaffected.
* Callback may return a promise that will be awaited for.
* @param {Function} callback
* @returns {Q.Promise}
* @example
* doSomething()
* .then(...)
* .tap(console.log)
* .then(...);
*/
Promise.prototype.tap = function (callback) {
callback = Q(callback);
return this.then(function (value) {
return callback.fcall(value).thenResolve(value);
});
};
/**
* Registers an observer on a promise.
*
* Guarantees:
*
* 1. that fulfilled and rejected will be called only once.
* 2. that either the fulfilled callback or the rejected callback will be
* called, but not both.
* 3. that fulfilled and rejected will not be called in this turn.
*
* @param value promise or immediate reference to observe
* @param fulfilled function to be called with the fulfilled value
* @param rejected function to be called with the rejection exception
* @param progressed function to be called on any progress notifications
* @return promise for the return value from the invoked callback
*/
Q.when = when;
function when(value, fulfilled, rejected, progressed) {
return Q(value).then(fulfilled, rejected, progressed);
}
Promise.prototype.thenResolve = function (value) {
return this.then(function () { return value; });
};
Q.thenResolve = function (promise, value) {
return Q(promise).thenResolve(value);
};
Promise.prototype.thenReject = function (reason) {
return this.then(function () { throw reason; });
};
Q.thenReject = function (promise, reason) {
return Q(promise).thenReject(reason);
};
/**
* If an object is not a promise, it is as "near" as possible.
* If a promise is rejected, it is as "near" as possible too.
* If it’s a fulfilled promise, the fulfillment value is nearer.
* If it’s a deferred promise and the deferred has been resolved, the
* resolution is "nearer".
* @param object
* @returns most resolved (nearest) form of the object
*/
// XXX should we re-do this?
Q.nearer = nearer;
function nearer(value) {
if (isPromise(value)) {
var inspected = value.inspect();
if (inspected.state === "fulfilled") {
return inspected.value;
}
}
return value;
}
/**
* @returns whether the given object is a promise.
* Otherwise it is a fulfilled value.
*/
Q.isPromise = isPromise;
function isPromise(object) {
return object instanceof Promise;
}
Q.isPromiseAlike = isPromiseAlike;
function isPromiseAlike(object) {
return isObject(object) && typeof object.then === "function";
}
/**
* @returns whether the given object is a pending promise, meaning not
* fulfilled or rejected.
*/
Q.isPending = isPending;
function isPending(object) {
return isPromise(object) && object.inspect().state === "pending";
}
Promise.prototype.isPending = function () {
return this.inspect().state === "pending";
};
/**
* @returns whether the given object is a value or fulfilled
* promise.
*/
Q.isFulfilled = isFulfilled;
function isFulfilled(object) {
return !isPromise(object) || object.inspect().state === "fulfilled";
}
Promise.prototype.isFulfilled = function () {
return this.inspect().state === "fulfilled";
};
/**
* @returns whether the given object is a rejected promise.
*/
Q.isRejected = isRejected;
function isRejected(object) {
return isPromise(object) && object.inspect().state === "rejected";
}
Promise.prototype.isRejected = function () {
return this.inspect().state === "rejected";
};
//// BEGIN UNHANDLED REJECTION TRACKING
// This promise library consumes exceptions thrown in handlers so they can be
// handled by a subsequent promise. The exceptions get added to this array when
// they are created, and removed when they are handled. Note that in ES6 or
// shimmed environments, this would naturally be a `Set`.
var unhandledReasons = [];
var unhandledRejections = [];
var reportedUnhandledRejections = [];
var trackUnhandledRejections = true;
function resetUnhandledRejections() {
unhandledReasons.length = 0;
unhandledRejections.length = 0;
Iif (!trackUnhandledRejections) {
trackUnhandledRejections = true;
}
}
function trackRejection(promise, reason) {
if (!trackUnhandledRejections) {
return;
}
if (typeof process === "object" && typeof process.emit === "function") {
Q.nextTick.runAfter(function () {
if (array_indexOf(unhandledRejections, promise) !== -1) {
process.emit("unhandledRejection", reason, promise);
reportedUnhandledRejections.push(promise);
}
});
}
unhandledRejections.push(promise);
if (reason && typeof reason.stack !== "undefined") {
unhandledReasons.push(reason.stack);
} else {
unhandledReasons.push("(no stack) " + reason);
}
}
function untrackRejection(promise) {
if (!trackUnhandledRejections) {
return;
}
var at = array_indexOf(unhandledRejections, promise);
if (at !== -1) {
if (typeof process === "object" && typeof process.emit === "function") {
Q.nextTick.runAfter(function () {
var atReport = array_indexOf(reportedUnhandledRejections, promise);
if (atReport !== -1) {
process.emit("rejectionHandled", unhandledReasons[at], promise);
reportedUnhandledRejections.splice(atReport, 1);
}
});
}
unhandledRejections.splice(at, 1);
unhandledReasons.splice(at, 1);
}
}
Q.resetUnhandledRejections = resetUnhandledRejections;
Q.getUnhandledReasons = function () {
// Make a copy so that consumers can't interfere with our internal state.
return unhandledReasons.slice();
};
Q.stopUnhandledRejectionTracking = function () {
resetUnhandledRejections();
trackUnhandledRejections = false;
};
resetUnhandledRejections();
//// END UNHANDLED REJECTION TRACKING
/**
* Constructs a rejected promise.
* @param reason value describing the failure
*/
Q.reject = reject;
function reject(reason) {
var rejection = Promise({
"when": function (rejected) {
// note that the error has been handled
if (rejected) {
untrackRejection(this);
}
return rejected ? rejected(reason) : this;
}
}, function fallback() {
return this;
}, function inspect() {
return { state: "rejected", reason: reason };
});
// Note that the reason has not been handled.
trackRejection(rejection, reason);
return rejection;
}
/**
* Constructs a fulfilled promise for an immediate reference.
* @param value immediate reference
*/
Q.fulfill = fulfill;
function fulfill(value) {
return Promise({
"when": function () {
return value;
},
"get": function (name) {
return value[name];
},
"set": function (name, rhs) {
value[name] = rhs;
},
"delete": function (name) {
delete value[name];
},
"post": function (name, args) {
// Mark Miller proposes that post with no name should apply a
// promised function.
if (name === null || name === void 0) {
return value.apply(void 0, args);
} else {
return value[name].apply(value, args);
}
},
"apply": function (thisp, args) {
return value.apply(thisp, args);
},
"keys": function () {
return object_keys(value);
}
}, void 0, function inspect() {
return { state: "fulfilled", value: value };
});
}
/**
* Converts thenables to Q promises.
* @param promise thenable promise
* @returns a Q promise
*/
function coerce(promise) {
var deferred = defer();
Q.nextTick(function () {
try {
promise.then(deferred.resolve, deferred.reject, deferred.notify);
} catch (exception) {
deferred.reject(exception);
}
});
return deferred.promise;
}
/**
* Annotates an object such that it will never be
* transferred away from this process over any promise
* communication channel.
* @param object
* @returns promise a wrapping of that object that
* additionally responds to the "isDef" message
* without a rejection.
*/
Q.master = master;
function master(object) {
return Promise({
"isDef": function () {}
}, function fallback(op, args) {
return dispatch(object, op, args);
}, function () {
return Q(object).inspect();
});
}
/**
* Spreads the values of a promised array of arguments into the
* fulfillment callback.
* @param fulfilled callback that receives variadic arguments from the
* promised array
* @param rejected callback that receives the exception if the promise
* is rejected.
* @returns a promise for the return value or thrown exception of
* either callback.
*/
Q.spread = spread;
function spread(value, fulfilled, rejected) {
return Q(value).spread(fulfilled, rejected);
}
Promise.prototype.spread = function (fulfilled, rejected) {
return this.all().then(function (array) {
return fulfilled.apply(void 0, array);
}, rejected);
};
/**
* The async function is a decorator for generator functions, turning
* them into asynchronous generators. Although generators are only part
* of the newest ECMAScript 6 drafts, this code does not cause syntax
* errors in older engines. This code should continue to work and will
* in fact improve over time as the language improves.
*
* ES6 generators are currently part of V8 version 3.19 with the
* --harmony-generators runtime flag enabled. SpiderMonkey has had them
* for longer, but under an older Python-inspired form. This function
* works on both kinds of generators.
*
* Decorates a generator function such that:
* - it may yield promises
* - execution will continue when that promise is fulfilled
* - the value of the yield expression will be the fulfilled value
* - it returns a promise for the return value (when the generator
* stops iterating)
* - the decorated function returns a promise for the return value
* of the generator or the first rejected promise among those
* yielded.
* - if an error is thrown in the generator, it propagates through
* every following yield until it is caught, or until it escapes
* the generator function altogether, and is translated into a
* rejection for the promise returned by the decorated generator.
*/
Q.async = async;
function async(makeGenerator) {
return function () {
// when verb is "send", arg is a value
// when verb is "throw", arg is an exception
function continuer(verb, arg) {
var result;
// Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
// engine that has a deployed base of browsers that support generators.
// However, SM's generators use the Python-inspired semantics of
// outdated ES6 drafts. We would like to support ES6, but we'd also
// like to make it possible to use generators in deployed browsers, so
// we also support Python-style generators. At some point we can remove
// this block.
if (typeof StopIteration === "undefined") {
// ES6 Generators
try {
result = generator[verb](arg);
} catch (exception) {
return reject(exception);
}
if (result.done) {
return Q(result.value);
} else {
return when(result.value, callback, errback);
}
} else {
// SpiderMonkey Generators
// FIXME: Remove this case when SM does ES6 generators.
try {
result = generator[verb](arg);
} catch (exception) {
if (isStopIteration(exception)) {
return Q(exception.value);
} else {
return reject(exception);
}
}
return when(result, callback, errback);
}
}
var generator = makeGenerator.apply(this, arguments);
var callback = continuer.bind(continuer, "next");
var errback = continuer.bind(continuer, "throw");
return callback();
};
}
/**
* The spawn function is a small wrapper around async that immediately
* calls the generator and also ends the promise chain, so that any
* unhandled errors are thrown instead of forwarded to the error
* handler. This is useful because it's extremely common to run
* generators at the top-level to work with libraries.
*/
Q.spawn = spawn;
function spawn(makeGenerator) {
Q.done(Q.async(makeGenerator)());
}
// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
/**
* Throws a ReturnValue exception to stop an asynchronous generator.
*
* This interface is a stop-gap measure to support generator return
* values in older Firefox/SpiderMonkey. In browsers that support ES6
* generators like Chromium 29, just use "return" in your generator
* functions.
*
* @param value the return value for the surrounding generator
* @throws ReturnValue exception with the value.
* @example
* // ES6 style
* Q.async(function* () {
* var foo = yield getFooPromise();
* var bar = yield getBarPromise();
* return foo + bar;
* })
* // Older SpiderMonkey style
* Q.async(function () {
* var foo = yield getFooPromise();
* var bar = yield getBarPromise();
* Q.return(foo + bar);
* })
*/
Q["return"] = _return;
function _return(value) {
throw new QReturnValue(value);
}
/**
* The promised function decorator ensures that any promise arguments
* are settled and passed as values (`this` is also settled and passed
* as a value). It will also ensure that the result of a function is
* always a promise.
*
* @example
* var add = Q.promised(function (a, b) {
* return a + b;
* });
* add(Q(a), Q(B));
*
* @param {function} callback The function to decorate
* @returns {function} a function that has been decorated.
*/
Q.promised = promised;
function promised(callback) {
return function () {
return spread([this, all(arguments)], function (self, args) {
return callback.apply(self, args);
});
};
}
/**
* sends a message to a value in a future turn
* @param object* the recipient
* @param op the name of the message operation, e.g., "when",
* @param args further arguments to be forwarded to the operation
* @returns result {Promise} a promise for the result of the operation
*/
Q.dispatch = dispatch;
function dispatch(object, op, args) {
return Q(object).dispatch(op, args);
}
Promise.prototype.dispatch = function (op, args) {
var self = this;
var deferred = defer();
Q.nextTick(function () {
self.promiseDispatch(deferred.resolve, op, args);
});
return deferred.promise;
};
/**
* Gets the value of a property in a future turn.
* @param object promise or immediate reference for target object
* @param name name of property to get
* @return promise for the property value
*/
Q.get = function (object, key) {
return Q(object).dispatch("get", [key]);
};
Promise.prototype.get = function (key) {
return this.dispatch("get", [key]);
};
/**
* Sets the value of a property in a future turn.
* @param object promise or immediate reference for object object
* @param name name of property to set
* @param value new value of property
* @return promise for the return value
*/
Q.set = function (object, key, value) {
return Q(object).dispatch("set", [key, value]);
};
Promise.prototype.set = function (key, value) {
return this.dispatch("set", [key, value]);
};
/**
* Deletes a property in a future turn.
* @param object promise or immediate reference for target object
* @param name name of property to delete
* @return promise for the return value
*/
Q.del = // XXX legacy
Q["delete"] = function (object, key) {
return Q(object).dispatch("delete", [key]);
};
Promise.prototype.del = // XXX legacy
Promise.prototype["delete"] = function (key) {
return this.dispatch("delete", [key]);
};
/**
* Invokes a method in a future turn.
* @param object promise or immediate reference for target object
* @param name name of method to invoke
* @param value a value to post, typically an array of
* invocation arguments for promises that
* are ultimately backed with `resolve` values,
* as opposed to those backed with URLs
* wherein the posted value can be any
* JSON serializable object.
* @return promise for the return value
*/
// bound locally because it is used by other methods
Q.mapply = // XXX As proposed by "Redsandro"
Q.post = function (object, name, args) {
return Q(object).dispatch("post", [name, args]);
};
Promise.prototype.mapply = // XXX As proposed by "Redsandro"
Promise.prototype.post = function (name, args) {
return this.dispatch("post", [name, args]);
};
/**
* Invokes a method in a future turn.
* @param object promise or immediate reference for target object
* @param name name of method to invoke
* @param ...args array of invocation arguments
* @return promise for the return value
*/
Q.send = // XXX Mark Miller's proposed parlance
Q.mcall = // XXX As proposed by "Redsandro"
Q.invoke = function (object, name /*...args*/) {
return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
};
Promise.prototype.send = // XXX Mark Miller's proposed parlance
Promise.prototype.mcall = // XXX As proposed by "Redsandro"
Promise.prototype.invoke = function (name /*...args*/) {
return this.dispatch("post", [name, array_slice(arguments, 1)]);
};
/**
* Applies the promised function in a future turn.
* @param object promise or immediate reference for target function
* @param args array of application arguments
*/
Q.fapply = function (object, args) {
return Q(object).dispatch("apply", [void 0, args]);
};
Promise.prototype.fapply = function (args) {
return this.dispatch("apply", [void 0, args]);
};
/**
* Calls the promised function in a future turn.
* @param object promise or immediate reference for target function
* @param ...args array of application arguments
*/
Q["try"] =
Q.fcall = function (object /* ...args*/) {
return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
};
Promise.prototype.fcall = function (/*...args*/) {
return this.dispatch("apply", [void 0, array_slice(arguments)]);
};
/**
* Binds the promised function, transforming return values into a fulfilled
* promise and thrown errors into a rejected one.
* @param object promise or immediate reference for target function
* @param ...args array of application arguments
*/
Q.fbind = function (object /*...args*/) {
var promise = Q(object);
var args = array_slice(arguments, 1);
return function fbound() {
return promise.dispatch("apply", [
this,
args.concat(array_slice(arguments))
]);
};
};
Promise.prototype.fbind = function (/*...args*/) {
var promise = this;
var args = array_slice(arguments);
return function fbound() {
return promise.dispatch("apply", [
this,
args.concat(array_slice(arguments))
]);
};
};
/**
* Requests the names of the owned properties of a promised
* object in a future turn.
* @param object promise or immediate reference for target object
* @return promise for the keys of the eventually settled object
*/
Q.keys = function (object) {
return Q(object).dispatch("keys", []);
};
Promise.prototype.keys = function () {
return this.dispatch("keys", []);
};
/**
* Turns an array of promises into a promise for an array. If any of
* the promises gets rejected, the whole array is rejected immediately.
* @param {Array*} an array (or promise for an array) of values (or
* promises for values)
* @returns a promise for an array of the corresponding values
*/
// By Mark Miller
// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
Q.all = all;
function all(promises) {
return when(promises, function (promises) {
var pendingCount = 0;
var deferred = defer();
array_reduce(promises, function (undefined, promise, index) {
var snapshot;
if (
isPromise(promise) &&
(snapshot = promise.inspect()).state === "fulfilled"
) {
promises[index] = snapshot.value;
} else {
++pendingCount;
when(
promise,
function (value) {
promises[index] = value;
if (--pendingCount === 0) {
deferred.resolve(promises);
}
},
deferred.reject,
function (progress) {
deferred.notify({ index: index, value: progress });
}
);
}
}, void 0);
if (pendingCount === 0) {
deferred.resolve(promises);
}
return deferred.promise;
});
}
Promise.prototype.all = function () {
return all(this);
};
/**
* Returns the first resolved promise of an array. Prior rejected promises are
* ignored. Rejects only if all promises are rejected.
* @param {Array*} an array containing values or promises for values
* @returns a promise fulfilled with the value of the first resolved promise,
* or a rejected promise if all promises are rejected.
*/
Q.any = any;
function any(promises) {
if (promises.length === 0) {
return Q.resolve();
}
var deferred = Q.defer();
var pendingCount = 0;
array_reduce(promises, function (prev, current, index) {
var promise = promises[index];
pendingCount++;
when(promise, onFulfilled, onRejected, onProgress);
function onFulfilled(result) {
deferred.resolve(result);
}
function onRejected() {
pendingCount--;
if (pendingCount === 0) {
deferred.reject(new Error(
"Can't get fulfillment value from any promise, all " +
"promises were rejected."
));
}
}
function onProgress(progress) {
deferred.notify({
index: index,
value: progress
});
}
}, undefined);
return deferred.promise;
}
Promise.prototype.any = function () {
return any(this);
};
/**
* Waits for all promises to be settled, either fulfilled or
* rejected. This is distinct from `all` since that would stop
* waiting at the first rejection. The promise returned by
* `allResolved` will never be rejected.
* @param promises a promise for an array (or an array) of promises
* (or values)
* @return a promise for an array of promises
*/
Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
function allResolved(promises) {
return when(promises, function (promises) {
promises = array_map(promises, Q);
return when(all(array_map(promises, function (promise) {
return when(promise, noop, noop);
})), function () {
return promises;
});
});
}
Promise.prototype.allResolved = function () {
return allResolved(this);
};
/**
* @see Promise#allSettled
*/
Q.allSettled = allSettled;
function allSettled(promises) {
return Q(promises).allSettled();
}
/**
* Turns an array of promises into a promise for an array of their states (as
* returned by `inspect`) when they have all settled.
* @param {Array[Any*]} values an array (or promise for an array) of values (or
* promises for values)
* @returns {Array[State]} an array of states for the respective values.
*/
Promise.prototype.allSettled = function () {
return this.then(function (promises) {
return all(array_map(promises, function (promise) {
promise = Q(promise);
function regardless() {
return promise.inspect();
}
return promise.then(regardless, regardless);
}));
});
};
/**
* Captures the failure of a promise, giving an oportunity to recover
* with a callback. If the given promise is fulfilled, the returned
* promise is fulfilled.
* @param {Any*} promise for something
* @param {Function} callback to fulfill the returned promise if the
* given promise is rejected
* @returns a promise for the return value of the callback
*/
Q.fail = // XXX legacy
Q["catch"] = function (object, rejected) {
return Q(object).then(void 0, rejected);
};
Promise.prototype.fail = // XXX legacy
Promise.prototype["catch"] = function (rejected) {
return this.then(void 0, rejected);
};
/**
* Attaches a listener that can respond to progress notifications from a
* promise's originating deferred. This listener receives the exact arguments
* passed to ``deferred.notify``.
* @param {Any*} promise for something
* @param {Function} callback to receive any progress notifications
* @returns the given promise, unchanged
*/
Q.progress = progress;
function progress(object, progressed) {
return Q(object).then(void 0, void 0, progressed);
}
Promise.prototype.progress = function (progressed) {
return this.then(void 0, void 0, progressed);
};
/**
* Provides an opportunity to observe the settling of a promise,
* regardless of whether the promise is fulfilled or rejected. Forwards
* the resolution to the returned promise when the callback is done.
* The callback can return a promise to defer completion.
* @param {Any*} promise
* @param {Function} callback to observe the resolution of the given
* promise, takes no arguments.
* @returns a promise for the resolution of the given promise when
* ``fin`` is done.
*/
Q.fin = // XXX legacy
Q["finally"] = function (object, callback) {
return Q(object)["finally"](callback);
};
Promise.prototype.fin = // XXX legacy
Promise.prototype["finally"] = function (callback) {
callback = Q(callback);
return this.then(function (value) {
return callback.fcall().then(function () {
return value;
});
}, function (reason) {
// TODO attempt to recycle the rejection with "this".
return callback.fcall().then(function () {
throw reason;
});
});
};
/**
* Terminates a chain of promises, forcing rejections to be
* thrown as exceptions.
* @param {Any*} promise at the end of a chain of promises
* @returns nothing
*/
Q.done = function (object, fulfilled, rejected, progress) {
return Q(object).done(fulfilled, rejected, progress);
};
Promise.prototype.done = function (fulfilled, rejected, progress) {
var onUnhandledError = function (error) {
// forward to a future turn so that ``when``
// does not catch it and turn it into a rejection.
Q.nextTick(function () {
makeStackTraceLong(error, promise);
if (Q.onerror) {
Q.onerror(error);
} else {
throw error;
}
});
};
// Avoid unnecessary `nextTick`ing via an unnecessary `when`.
var promise = fulfilled || rejected || progress ?
this.then(fulfilled, rejected, progress) :
this;
if (typeof process === "object" && process && process.domain) {
onUnhandledError = process.domain.bind(onUnhandledError);
}
promise.then(void 0, onUnhandledError);
};
/**
* Causes a promise to be rejected if it does not get fulfilled before
* some milliseconds time out.
* @param {Any*} promise
* @param {Number} milliseconds timeout
* @param {Any*} custom error message or Error object (optional)
* @returns a promise for the resolution of the given promise if it is
* fulfilled before the timeout, otherwise rejected.
*/
Q.timeout = function (object, ms, error) {
return Q(object).timeout(ms, error);
};
Promise.prototype.timeout = function (ms, error) {
var deferred = defer();
var timeoutId = setTimeout(function () {
if (!error || "string" === typeof error) {
error = new Error(error || "Timed out after " + ms + " ms");
error.code = "ETIMEDOUT";
}
deferred.reject(error);
}, ms);
this.then(function (value) {
clearTimeout(timeoutId);
deferred.resolve(value);
}, function (exception) {
clearTimeout(timeoutId);
deferred.reject(exception);
}, deferred.notify);
return deferred.promise;
};
/**
* Returns a promise for the given value (or promised value), some
* milliseconds after it resolved. Passes rejections immediately.
* @param {Any*} promise
* @param {Number} milliseconds
* @returns a promise for the resolution of the given promise after milliseconds
* time has elapsed since the resolution of the given promise.
* If the given promise rejects, that is passed immediately.
*/
Q.delay = function (object, timeout) {
if (timeout === void 0) {
timeout = object;
object = void 0;
}
return Q(object).delay(timeout);
};
Promise.prototype.delay = function (timeout) {
return this.then(function (value) {
var deferred = defer();
setTimeout(function () {
deferred.resolve(value);
}, timeout);
return deferred.promise;
});
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided as an array, and returns a promise.
*
* Q.nfapply(FS.readFile, [__filename])
* .then(function (content) {
* })
*
*/
Q.nfapply = function (callback, args) {
return Q(callback).nfapply(args);
};
Promise.prototype.nfapply = function (args) {
var deferred = defer();
var nodeArgs = array_slice(args);
nodeArgs.push(deferred.makeNodeResolver());
this.fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
/**
* Passes a continuation to a Node function, which is called with the given
* arguments provided individually, and returns a promise.
* @example
* Q.nfcall(FS.readFile, __filename)
* .then(function (content) {
* })
*
*/
Q.nfcall = function (callback /*...args*/) {
var args = array_slice(arguments, 1);
return Q(callback).nfapply(args);
};
Promise.prototype.nfcall = function (/*...args*/) {
var nodeArgs = array_slice(arguments);
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
this.fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
/**
* Wraps a NodeJS continuation passing function and returns an equivalent
* version that returns a promise.
* @example
* Q.nfbind(FS.readFile, __filename)("utf-8")
* .then(console.log)
* .done()
*/
Q.nfbind =
Q.denodeify = function (callback /*...args*/) {
var baseArgs = array_slice(arguments, 1);
return function () {
var nodeArgs = baseArgs.concat(array_slice(arguments));
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
Q(callback).fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
};
Promise.prototype.nfbind =
Promise.prototype.denodeify = function (/*...args*/) {
var args = array_slice(arguments);
args.unshift(this);
return Q.denodeify.apply(void 0, args);
};
Q.nbind = function (callback, thisp /*...args*/) {
var baseArgs = array_slice(arguments, 2);
return function () {
var nodeArgs = baseArgs.concat(array_slice(arguments));
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
function bound() {
return callback.apply(thisp, arguments);
}
Q(bound).fapply(nodeArgs).fail(deferred.reject);
return deferred.promise;
};
};
Promise.prototype.nbind = function (/*thisp, ...args*/) {
var args = array_slice(arguments, 0);
args.unshift(this);
return Q.nbind.apply(void 0, args);
};
/**
* Calls a method of a Node-style object that accepts a Node-style
* callback with a given array of arguments, plus a provided callback.
* @param object an object that has the named method
* @param {String} name name of the method of object
* @param {Array} args arguments to pass to the method; the callback
* will be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
Q.nmapply = // XXX As proposed by "Redsandro"
Q.npost = function (object, name, args) {
return Q(object).npost(name, args);
};
Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
Promise.prototype.npost = function (name, args) {
var nodeArgs = array_slice(args || []);
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
return deferred.promise;
};
/**
* Calls a method of a Node-style object that accepts a Node-style
* callback, forwarding the given variadic arguments, plus a provided
* callback argument.
* @param object an object that has the named method
* @param {String} name name of the method of object
* @param ...args arguments to pass to the method; the callback will
* be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
Q.nsend = // XXX Based on Mark Miller's proposed "send"
Q.nmcall = // XXX Based on "Redsandro's" proposal
Q.ninvoke = function (object, name /*...args*/) {
var nodeArgs = array_slice(arguments, 2);
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject);
return deferred.promise;
};
Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
Promise.prototype.ninvoke = function (name /*...args*/) {
var nodeArgs = array_slice(arguments, 1);
var deferred = defer();
nodeArgs.push(deferred.makeNodeResolver());
this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
return deferred.promise;
};
/**
* If a function would like to support both Node continuation-passing-style and
* promise-returning-style, it can end its internal promise chain with
* `nodeify(nodeback)`, forwarding the optional nodeback argument. If the user
* elects to use a nodeback, the result will be sent there. If they do not
* pass a nodeback, they will receive the result promise.
* @param object a result (or a promise for a result)
* @param {Function} nodeback a Node.js-style callback
* @returns either the promise or nothing
*/
Q.nodeify = nodeify;
function nodeify(object, nodeback) {
return Q(object).nodeify(nodeback);
}
Promise.prototype.nodeify = function (nodeback) {
if (nodeback) {
this.then(function (value) {
Q.nextTick(function () {
nodeback(null, value);
});
}, function (error) {
Q.nextTick(function () {
nodeback(error);
});
});
} else {
return this;
}
};
Q.noConflict = function() {
throw new Error("Q.noConflict only works when Q is used as a global");
};
// All code before this point will be filtered from stack traces.
var qEndingLine = captureLine();
return Q;
});
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| shell.js | 100% | (52 / 52) | 100% | (0 / 0) | 100% | (0 / 0) | 100% | (52 / 52) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | //
// ShellJS
// Unix shell commands on top of Node's API
//
// Copyright (c) 2012 Artur Adib
// http://github.com/arturadib/shelljs
//
var common = require('./src/common');
//@
//@ All commands run synchronously, unless otherwise stated.
//@
//@include ./src/cd
var _cd = require('./src/cd');
exports.cd = common.wrap('cd', _cd);
//@include ./src/pwd
var _pwd = require('./src/pwd');
exports.pwd = common.wrap('pwd', _pwd);
//@include ./src/ls
var _ls = require('./src/ls');
exports.ls = common.wrap('ls', _ls);
//@include ./src/find
var _find = require('./src/find');
exports.find = common.wrap('find', _find);
//@include ./src/cp
var _cp = require('./src/cp');
exports.cp = common.wrap('cp', _cp);
//@include ./src/rm
var _rm = require('./src/rm');
exports.rm = common.wrap('rm', _rm);
//@include ./src/mv
var _mv = require('./src/mv');
exports.mv = common.wrap('mv', _mv);
//@include ./src/mkdir
var _mkdir = require('./src/mkdir');
exports.mkdir = common.wrap('mkdir', _mkdir);
//@include ./src/test
var _test = require('./src/test');
exports.test = common.wrap('test', _test);
//@include ./src/cat
var _cat = require('./src/cat');
exports.cat = common.wrap('cat', _cat);
//@include ./src/to
var _to = require('./src/to');
String.prototype.to = common.wrap('to', _to);
//@include ./src/toEnd
var _toEnd = require('./src/toEnd');
String.prototype.toEnd = common.wrap('toEnd', _toEnd);
//@include ./src/sed
var _sed = require('./src/sed');
exports.sed = common.wrap('sed', _sed);
//@include ./src/grep
var _grep = require('./src/grep');
exports.grep = common.wrap('grep', _grep);
//@include ./src/which
var _which = require('./src/which');
exports.which = common.wrap('which', _which);
//@include ./src/echo
var _echo = require('./src/echo');
exports.echo = _echo; // don't common.wrap() as it could parse '-options'
//@include ./src/dirs
var _dirs = require('./src/dirs').dirs;
exports.dirs = common.wrap("dirs", _dirs);
var _pushd = require('./src/dirs').pushd;
exports.pushd = common.wrap('pushd', _pushd);
var _popd = require('./src/dirs').popd;
exports.popd = common.wrap("popd", _popd);
//@include ./src/ln
var _ln = require('./src/ln');
exports.ln = common.wrap('ln', _ln);
//@
//@ ### exit(code)
//@ Exits the current process with the given exit code.
exports.exit = process.exit;
//@
//@ ### env['VAR_NAME']
//@ Object containing environment variables (both getter and setter). Shortcut to process.env.
exports.env = process.env;
//@include ./src/exec
var _exec = require('./src/exec');
exports.exec = common.wrap('exec', _exec, {notUnix:true});
//@include ./src/chmod
var _chmod = require('./src/chmod');
exports.chmod = common.wrap('chmod', _chmod);
//@
//@ ## Non-Unix commands
//@
//@include ./src/tempdir
var _tempDir = require('./src/tempdir');
exports.tempdir = common.wrap('tempdir', _tempDir);
//@include ./src/error
var _error = require('./src/error');
exports.error = _error;
//@
//@ ## Configuration
//@
exports.config = common.config;
//@
//@ ### config.silent
//@ Example:
//@
//@ ```javascript
//@ var sh = require('shelljs');
//@ var silentState = sh.config.silent; // save old silent state
//@ sh.config.silent = true;
//@ /* ... */
//@ sh.config.silent = silentState; // restore old silent state
//@ ```
//@
//@ Suppresses all command output if `true`, except for `echo()` calls.
//@ Default is `false`.
//@
//@ ### config.fatal
//@ Example:
//@
//@ ```javascript
//@ require('shelljs/global');
//@ config.fatal = true;
//@ cp('this_file_does_not_exist', '/dev/null'); // dies here
//@ /* more commands... */
//@ ```
//@
//@ If `true` the script will die on errors. Default is `false`.
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| cat.js | 23.53% | (4 / 17) | 0% | (0 / 8) | 0% | (0 / 2) | 23.53% | (4 / 17) | |
| cd.js | 36.36% | (4 / 11) | 0% | (0 / 6) | 0% | (0 / 1) | 36.36% | (4 / 11) | |
| chmod.js | 8.64% | (7 / 81) | 0% | (0 / 78) | 16.67% | (1 / 6) | 8.64% | (7 / 81) | |
| common.js | 26.13% | (29 / 111) | 2.13% | (1 / 47) | 5.88% | (1 / 17) | 26.13% | (29 / 111) | |
| cp.js | 8.99% | (8 / 89) | 0% | (0 / 56) | 0% | (0 / 5) | 9.2% | (8 / 87) | |
| dirs.js | 18.06% | (13 / 72) | 0% | (0 / 41) | 0% | (0 / 6) | 18.06% | (13 / 72) | |
| echo.js | 50% | (3 / 6) | 100% | (0 / 0) | 0% | (0 / 1) | 50% | (3 / 6) | |
| error.js | 75% | (3 / 4) | 100% | (0 / 0) | 0% | (0 / 1) | 75% | (3 / 4) | |
| exec.js | 13.33% | (12 / 90) | 0% | (0 / 39) | 0% | (0 / 8) | 15.19% | (12 / 79) | |
| find.js | 27.27% | (6 / 22) | 0% | (0 / 10) | 0% | (0 / 4) | 27.27% | (6 / 22) | |
| grep.js | 19.05% | (4 / 21) | 0% | (0 / 12) | 0% | (0 / 3) | 19.05% | (4 / 21) | |
| ln.js | 30% | (6 / 20) | 0% | (0 / 16) | 0% | (0 / 1) | 30% | (6 / 20) | |
| ls.js | 13.56% | (8 / 59) | 0% | (0 / 47) | 0% | (0 / 5) | 13.56% | (8 / 59) | |
| mkdir.js | 20.69% | (6 / 29) | 0% | (0 / 16) | 0% | (0 / 3) | 20.69% | (6 / 29) | |
| mv.js | 13.89% | (5 / 36) | 0% | (0 / 32) | 0% | (0 / 2) | 13.89% | (5 / 36) | |
| pwd.js | 66.67% | (4 / 6) | 100% | (0 / 0) | 0% | (0 / 1) | 66.67% | (4 / 6) | |
| rm.js | 8.7% | (6 / 69) | 0% | (0 / 49) | 0% | (0 / 4) | 8.96% | (6 / 67) | |
| sed.js | 22.22% | (4 / 18) | 0% | (0 / 12) | 0% | (0 / 1) | 22.22% | (4 / 18) | |
| tempdir.js | 28.57% | (6 / 21) | 0% | (0 / 23) | 0% | (0 / 2) | 28.57% | (6 / 21) | |
| test.js | 11.43% | (4 / 35) | 0% | (0 / 24) | 0% | (0 / 1) | 11.43% | (4 / 35) | |
| to.js | 41.67% | (5 / 12) | 0% | (0 / 4) | 0% | (0 / 1) | 41.67% | (5 / 12) | |
| toEnd.js | 41.67% | (5 / 12) | 0% | (0 / 4) | 0% | (0 / 1) | 41.67% | (5 / 12) | |
| which.js | 16.28% | (7 / 43) | 0% | (0 / 31) | 0% | (0 / 4) | 16.28% | (7 / 43) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 1 1 1 1 | var common = require('./common');
var fs = require('fs');
//@
//@ ### cat(file [, file ...])
//@ ### cat(file_array)
//@
//@ Examples:
//@
//@ ```javascript
//@ var str = cat('file*.txt');
//@ var str = cat('file1', 'file2');
//@ var str = cat(['file1', 'file2']); // same as above
//@ ```
//@
//@ Returns a string containing the given file, or a concatenated string
//@ containing the files if more than one file is given (a new line character is
//@ introduced between each file). Wildcard `*` accepted.
function _cat(options, files) {
var cat = '';
if (!files)
common.error('no paths given');
if (typeof files === 'string')
files = [].slice.call(arguments, 1);
// if it's array leave it as it is
files = common.expand(files);
files.forEach(function(file) {
if (!fs.existsSync(file))
common.error('no such file or directory: ' + file);
cat += fs.readFileSync(file, 'utf8') + '\n';
});
if (cat[cat.length-1] === '\n')
cat = cat.substring(0, cat.length-1);
return common.ShellString(cat);
}
module.exports = _cat;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 1 1 1 1 | var fs = require('fs');
var common = require('./common');
//@
//@ ### cd('dir')
//@ Changes to directory `dir` for the duration of the script
function _cd(options, dir) {
if (!dir)
common.error('directory not specified');
if (!fs.existsSync(dir))
common.error('no such file or directory: ' + dir);
if (!fs.statSync(dir).isDirectory())
common.error('not a directory: ' + dir);
process.chdir(dir);
}
module.exports = _cd;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | 1 1 1 1 1 1 1 | var common = require('./common');
var fs = require('fs');
var path = require('path');
var PERMS = (function (base) {
return {
OTHER_EXEC : base.EXEC,
OTHER_WRITE : base.WRITE,
OTHER_READ : base.READ,
GROUP_EXEC : base.EXEC << 3,
GROUP_WRITE : base.WRITE << 3,
GROUP_READ : base.READ << 3,
OWNER_EXEC : base.EXEC << 6,
OWNER_WRITE : base.WRITE << 6,
OWNER_READ : base.READ << 6,
// Literal octal numbers are apparently not allowed in "strict" javascript. Using parseInt is
// the preferred way, else a jshint warning is thrown.
STICKY : parseInt('01000', 8),
SETGID : parseInt('02000', 8),
SETUID : parseInt('04000', 8),
TYPE_MASK : parseInt('0770000', 8)
};
})({
EXEC : 1,
WRITE : 2,
READ : 4
});
//@
//@ ### chmod(octal_mode || octal_string, file)
//@ ### chmod(symbolic_mode, file)
//@
//@ Available options:
//@
//@ + `-v`: output a diagnostic for every file processed//@
//@ + `-c`: like verbose but report only when a change is made//@
//@ + `-R`: change files and directories recursively//@
//@
//@ Examples:
//@
//@ ```javascript
//@ chmod(755, '/Users/brandon');
//@ chmod('755', '/Users/brandon'); // same as above
//@ chmod('u+x', '/Users/brandon');
//@ ```
//@
//@ Alters the permissions of a file or directory by either specifying the
//@ absolute permissions in octal form or expressing the changes in symbols.
//@ This command tries to mimic the POSIX behavior as much as possible.
//@ Notable exceptions:
//@
//@ + In symbolic modes, 'a-r' and '-r' are identical. No consideration is
//@ given to the umask.
//@ + There is no "quiet" option since default behavior is to run silent.
function _chmod(options, mode, filePattern) {
if (!filePattern) {
if (options.length > 0 && options.charAt(0) === '-') {
// Special case where the specified file permissions started with - to subtract perms, which
// get picked up by the option parser as command flags.
// If we are down by one argument and options starts with -, shift everything over.
filePattern = mode;
mode = options;
options = '';
}
else {
common.error('You must specify a file.');
}
}
options = common.parseOptions(options, {
'R': 'recursive',
'c': 'changes',
'v': 'verbose'
});
if (typeof filePattern === 'string') {
filePattern = [ filePattern ];
}
var files;
if (options.recursive) {
files = [];
common.expand(filePattern).forEach(function addFile(expandedFile) {
var stat = fs.lstatSync(expandedFile);
if (!stat.isSymbolicLink()) {
files.push(expandedFile);
if (stat.isDirectory()) { // intentionally does not follow symlinks.
fs.readdirSync(expandedFile).forEach(function (child) {
addFile(expandedFile + '/' + child);
});
}
}
});
}
else {
files = common.expand(filePattern);
}
files.forEach(function innerChmod(file) {
file = path.resolve(file);
if (!fs.existsSync(file)) {
common.error('File not found: ' + file);
}
// When recursing, don't follow symlinks.
if (options.recursive && fs.lstatSync(file).isSymbolicLink()) {
return;
}
var perms = fs.statSync(file).mode;
var type = perms & PERMS.TYPE_MASK;
var newPerms = perms;
if (isNaN(parseInt(mode, 8))) {
// parse options
mode.split(',').forEach(function (symbolicMode) {
/*jshint regexdash:true */
var pattern = /([ugoa]*)([=\+-])([rwxXst]*)/i;
var matches = pattern.exec(symbolicMode);
if (matches) {
var applyTo = matches[1];
var operator = matches[2];
var change = matches[3];
var changeOwner = applyTo.indexOf('u') != -1 || applyTo === 'a' || applyTo === '';
var changeGroup = applyTo.indexOf('g') != -1 || applyTo === 'a' || applyTo === '';
var changeOther = applyTo.indexOf('o') != -1 || applyTo === 'a' || applyTo === '';
var changeRead = change.indexOf('r') != -1;
var changeWrite = change.indexOf('w') != -1;
var changeExec = change.indexOf('x') != -1;
var changeSticky = change.indexOf('t') != -1;
var changeSetuid = change.indexOf('s') != -1;
var mask = 0;
if (changeOwner) {
mask |= (changeRead ? PERMS.OWNER_READ : 0) + (changeWrite ? PERMS.OWNER_WRITE : 0) + (changeExec ? PERMS.OWNER_EXEC : 0) + (changeSetuid ? PERMS.SETUID : 0);
}
if (changeGroup) {
mask |= (changeRead ? PERMS.GROUP_READ : 0) + (changeWrite ? PERMS.GROUP_WRITE : 0) + (changeExec ? PERMS.GROUP_EXEC : 0) + (changeSetuid ? PERMS.SETGID : 0);
}
if (changeOther) {
mask |= (changeRead ? PERMS.OTHER_READ : 0) + (changeWrite ? PERMS.OTHER_WRITE : 0) + (changeExec ? PERMS.OTHER_EXEC : 0);
}
// Sticky bit is special - it's not tied to user, group or other.
if (changeSticky) {
mask |= PERMS.STICKY;
}
switch (operator) {
case '+':
newPerms |= mask;
break;
case '-':
newPerms &= ~mask;
break;
case '=':
newPerms = type + mask;
// According to POSIX, when using = to explicitly set the permissions, setuid and setgid can never be cleared.
if (fs.statSync(file).isDirectory()) {
newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms;
}
break;
}
if (options.verbose) {
log(file + ' -> ' + newPerms.toString(8));
}
if (perms != newPerms) {
if (!options.verbose && options.changes) {
log(file + ' -> ' + newPerms.toString(8));
}
fs.chmodSync(file, newPerms);
}
}
else {
common.error('Invalid symbolic mode change: ' + symbolicMode);
}
});
}
else {
// they gave us a full number
newPerms = type + parseInt(mode, 8);
// POSIX rules are that setuid and setgid can only be added using numeric form, but not cleared.
if (fs.statSync(file).isDirectory()) {
newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms;
}
fs.chmodSync(file, newPerms);
}
});
}
module.exports = _chmod;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 22 1 | var os = require('os');
var fs = require('fs');
var _ls = require('./ls');
// Module globals
var config = {
silent: false,
fatal: false
};
exports.config = config;
var state = {
error: null,
currentCmd: 'shell.js',
tempDir: null
};
exports.state = state;
var platform = os.type().match(/^Win/) ? 'win' : 'unix';
exports.platform = platform;
function log() {
if (!config.silent)
console.log.apply(this, arguments);
}
exports.log = log;
// Shows error message. Throws unless _continue or config.fatal are true
function error(msg, _continue) {
if (state.error === null)
state.error = '';
state.error += state.currentCmd + ': ' + msg + '\n';
if (msg.length > 0)
log(state.error);
if (config.fatal)
process.exit(1);
if (!_continue)
throw '';
}
exports.error = error;
// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings.
// For now, this is a dummy function to bookmark places we need such strings
function ShellString(str) {
return str;
}
exports.ShellString = ShellString;
// Returns {'alice': true, 'bob': false} when passed a dictionary, e.g.:
// parseOptions('-a', {'a':'alice', 'b':'bob'});
function parseOptions(str, map) {
if (!map)
error('parseOptions() internal error: no map given');
// All options are false by default
var options = {};
for (var letter in map)
options[map[letter]] = false;
if (!str)
return options; // defaults
if (typeof str !== 'string')
error('parseOptions() internal error: wrong str');
// e.g. match[1] = 'Rf' for str = '-Rf'
var match = str.match(/^\-(.+)/);
if (!match)
return options;
// e.g. chars = ['R', 'f']
var chars = match[1].split('');
chars.forEach(function(c) {
if (c in map)
options[map[c]] = true;
else
error('option not recognized: '+c);
});
return options;
}
exports.parseOptions = parseOptions;
// Expands wildcards with matching (ie. existing) file names.
// For example:
// expand(['file*.js']) = ['file1.js', 'file2.js', ...]
// (if the files 'file1.js', 'file2.js', etc, exist in the current dir)
function expand(list) {
var expanded = [];
list.forEach(function(listEl) {
// Wildcard present on directory names ?
if(listEl.search(/\*[^\/]*\//) > -1 || listEl.search(/\*\*[^\/]*\//) > -1) {
var match = listEl.match(/^([^*]+\/|)(.*)/);
var root = match[1];
var rest = match[2];
var restRegex = rest.replace(/\*\*/g, ".*").replace(/\*/g, "[^\\/]*");
restRegex = new RegExp(restRegex);
_ls('-R', root).filter(function (e) {
return restRegex.test(e);
}).forEach(function(file) {
expanded.push(file);
});
}
// Wildcard present on file names ?
else if (listEl.search(/\*/) > -1) {
_ls('', listEl).forEach(function(file) {
expanded.push(file);
});
} else {
expanded.push(listEl);
}
});
return expanded;
}
exports.expand = expand;
// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e.
// file can be unlinked even if it's read-only, see https://github.com/joyent/node/issues/3006
function unlinkSync(file) {
try {
fs.unlinkSync(file);
} catch(e) {
// Try to override file permission
if (e.code === 'EPERM') {
fs.chmodSync(file, '0666');
fs.unlinkSync(file);
} else {
throw e;
}
}
}
exports.unlinkSync = unlinkSync;
// e.g. 'shelljs_a5f185d0443ca...'
function randomFileName() {
function randomHash(count) {
if (count === 1)
return parseInt(16*Math.random(), 10).toString(16);
else {
var hash = '';
for (var i=0; i<count; i++)
hash += randomHash(1);
return hash;
}
}
return 'shelljs_'+randomHash(20);
}
exports.randomFileName = randomFileName;
// extend(target_obj, source_obj1 [, source_obj2 ...])
// Shallow extend, e.g.:
// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3}
function extend(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function(source) {
for (var key in source)
target[key] = source[key];
});
return target;
}
exports.extend = extend;
// Common wrapper for all Unix-like commands
function wrap(cmd, fn, options) {
return function() {
var retValue = null;
state.currentCmd = cmd;
state.error = null;
try {
var args = [].slice.call(arguments, 0);
if (options && options.notUnix) {
retValue = fn.apply(this, args);
} else {
if (args.length === 0 || typeof args[0] !== 'string' || args[0][0] !== '-')
args.unshift(''); // only add dummy option if '-option' not already present
retValue = fn.apply(this, args);
}
} catch (e) {
if (!state.error) {
// If state.error hasn't been set it's an error thrown by Node, not us - probably a bug...
console.log('shell.js: internal error');
console.log(e.stack || e);
process.exit(1);
}
if (config.fatal)
throw e;
}
state.currentCmd = 'shell.js';
return retValue;
};
} // wrap
exports.wrap = wrap;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | 1 1 1 1 1 1 1 1 | var fs = require('fs');
var path = require('path');
var common = require('./common');
var os = require('os');
// Buffered file copy, synchronous
// (Using readFileSync() + writeFileSync() could easily cause a memory overflow
// with large files)
function copyFileSync(srcFile, destFile) {
if (!fs.existsSync(srcFile))
common.error('copyFileSync: no such file or directory: ' + srcFile);
var BUF_LENGTH = 64*1024,
buf = new Buffer(BUF_LENGTH),
bytesRead = BUF_LENGTH,
pos = 0,
fdr = null,
fdw = null;
try {
fdr = fs.openSync(srcFile, 'r');
} catch(e) {
common.error('copyFileSync: could not read src file ('+srcFile+')');
}
try {
fdw = fs.openSync(destFile, 'w');
} catch(e) {
common.error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile);
}
while (bytesRead === BUF_LENGTH) {
bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
fs.writeSync(fdw, buf, 0, bytesRead);
pos += bytesRead;
}
fs.closeSync(fdr);
fs.closeSync(fdw);
fs.chmodSync(destFile, fs.statSync(srcFile).mode);
}
// Recursively copies 'sourceDir' into 'destDir'
// Adapted from https://github.com/ryanmcgrath/wrench-js
//
// Copyright (c) 2010 Ryan McGrath
// Copyright (c) 2012 Artur Adib
//
// Licensed under the MIT License
// http://www.opensource.org/licenses/mit-license.php
function cpdirSyncRecursive(sourceDir, destDir, opts) {
if (!opts) opts = {};
/* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
var checkDir = fs.statSync(sourceDir);
try {
fs.mkdirSync(destDir, checkDir.mode);
} catch (e) {
//if the directory already exists, that's okay
if (e.code !== 'EEXIST') throw e;
}
var files = fs.readdirSync(sourceDir);
for (var i = 0; i < files.length; i++) {
var srcFile = sourceDir + "/" + files[i];
var destFile = destDir + "/" + files[i];
var srcFileStat = fs.lstatSync(srcFile);
if (srcFileStat.isDirectory()) {
/* recursion this thing right on back. */
cpdirSyncRecursive(srcFile, destFile, opts);
} else if (srcFileStat.isSymbolicLink()) {
var symlinkFull = fs.readlinkSync(srcFile);
fs.symlinkSync(symlinkFull, destFile, os.platform() === "win32" ? "junction" : null);
} else {
/* At this point, we've hit a file actually worth copying... so copy it on over. */
if (fs.existsSync(destFile) && !opts.force) {
common.log('skipping existing file: ' + files[i]);
} else {
copyFileSync(srcFile, destFile);
}
}
} // for files
} // cpdirSyncRecursive
//@
//@ ### cp([options ,] source [,source ...], dest)
//@ ### cp([options ,] source_array, dest)
//@ Available options:
//@
//@ + `-f`: force
//@ + `-r, -R`: recursive
//@
//@ Examples:
//@
//@ ```javascript
//@ cp('file1', 'dir1');
//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');
//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above
//@ ```
//@
//@ Copies files. The wildcard `*` is accepted.
function _cp(options, sources, dest) {
options = common.parseOptions(options, {
'f': 'force',
'R': 'recursive',
'r': 'recursive'
});
// Get sources, dest
if (arguments.length < 3) {
common.error('missing <source> and/or <dest>');
} else if (arguments.length > 3) {
sources = [].slice.call(arguments, 1, arguments.length - 1);
dest = arguments[arguments.length - 1];
} else if (typeof sources === 'string') {
sources = [sources];
} else if ('length' in sources) {
sources = sources; // no-op for array
} else {
common.error('invalid arguments');
}
var exists = fs.existsSync(dest),
stats = exists && fs.statSync(dest);
// Dest is not existing dir, but multiple sources given
if ((!exists || !stats.isDirectory()) && sources.length > 1)
common.error('dest is not a directory (too many sources)');
// Dest is an existing file, but no -f given
if (exists && stats.isFile() && !options.force)
common.error('dest file already exists: ' + dest);
if (options.recursive) {
// Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*"
// (see Github issue #15)
sources.forEach(function(src, i) {
if (src[src.length - 1] === '/')
sources[i] += '*';
});
// Create dest
try {
fs.mkdirSync(dest, parseInt('0777', 8));
} catch (e) {
// like Unix's cp, keep going even if we can't create dest dir
}
}
sources = common.expand(sources);
sources.forEach(function(src) {
if (!fs.existsSync(src)) {
common.error('no such file or directory: '+src, true);
return; // skip file
}
// If here, src exists
if (fs.statSync(src).isDirectory()) {
if (!options.recursive) {
// Non-Recursive
common.log(src + ' is a directory (not copied)');
} else {
// Recursive
// 'cp /a/source dest' should create 'source' in 'dest'
var newDest = path.join(dest, path.basename(src)),
checkDir = fs.statSync(src);
try {
fs.mkdirSync(newDest, checkDir.mode);
} catch (e) {
//if the directory already exists, that's okay
if (e.code !== 'EEXIST') {
common.error('dest file no such file or directory: ' + newDest, true);
throw e;
}
}
cpdirSyncRecursive(src, newDest, {force: options.force});
}
return; // done with dir
}
// If here, src is a file
// When copying to '/path/dir':
// thisDest = '/path/dir/file1'
var thisDest = dest;
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
thisDest = path.normalize(dest + '/' + path.basename(src));
if (fs.existsSync(thisDest) && !options.force) {
common.error('dest file already exists: ' + thisDest, true);
return; // skip file
}
copyFileSync(src, thisDest);
}); // forEach(src)
}
module.exports = _cp;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | 1 1 1 1 1 1 1 1 1 1 1 1 1 | var common = require('./common');
var _cd = require('./cd');
var path = require('path');
// Pushd/popd/dirs internals
var _dirStack = [];
function _isStackIndex(index) {
return (/^[\-+]\d+$/).test(index);
}
function _parseStackIndex(index) {
if (_isStackIndex(index)) {
if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd
return (/^-/).test(index) ? Number(index) - 1 : Number(index);
} else {
common.error(index + ': directory stack index out of range');
}
} else {
common.error(index + ': invalid number');
}
}
function _actualDirStack() {
return [process.cwd()].concat(_dirStack);
}
//@
//@ ### pushd([options,] [dir | '-N' | '+N'])
//@
//@ Available options:
//@
//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.
//@
//@ Arguments:
//@
//@ + `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`.
//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
//@
//@ Examples:
//@
//@ ```javascript
//@ // process.cwd() === '/usr'
//@ pushd('/etc'); // Returns /etc /usr
//@ pushd('+1'); // Returns /usr /etc
//@ ```
//@
//@ Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack.
function _pushd(options, dir) {
if (_isStackIndex(options)) {
dir = options;
options = '';
}
options = common.parseOptions(options, {
'n' : 'no-cd'
});
var dirs = _actualDirStack();
if (dir === '+0') {
return dirs; // +0 is a noop
} else if (!dir) {
if (dirs.length > 1) {
dirs = dirs.splice(1, 1).concat(dirs);
} else {
return common.error('no other directory');
}
} else if (_isStackIndex(dir)) {
var n = _parseStackIndex(dir);
dirs = dirs.slice(n).concat(dirs.slice(0, n));
} else {
if (options['no-cd']) {
dirs.splice(1, 0, dir);
} else {
dirs.unshift(dir);
}
}
if (options['no-cd']) {
dirs = dirs.slice(1);
} else {
dir = path.resolve(dirs.shift());
_cd('', dir);
}
_dirStack = dirs;
return _dirs('');
}
exports.pushd = _pushd;
//@
//@ ### popd([options,] ['-N' | '+N'])
//@
//@ Available options:
//@
//@ + `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.
//@
//@ Arguments:
//@
//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
//@
//@ Examples:
//@
//@ ```javascript
//@ echo(process.cwd()); // '/usr'
//@ pushd('/etc'); // '/etc /usr'
//@ echo(process.cwd()); // '/etc'
//@ popd(); // '/usr'
//@ echo(process.cwd()); // '/usr'
//@ ```
//@
//@ When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack.
function _popd(options, index) {
if (_isStackIndex(options)) {
index = options;
options = '';
}
options = common.parseOptions(options, {
'n' : 'no-cd'
});
if (!_dirStack.length) {
return common.error('directory stack empty');
}
index = _parseStackIndex(index || '+0');
if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) {
index = index > 0 ? index - 1 : index;
_dirStack.splice(index, 1);
} else {
var dir = path.resolve(_dirStack.shift());
_cd('', dir);
}
return _dirs('');
}
exports.popd = _popd;
//@
//@ ### dirs([options | '+N' | '-N'])
//@
//@ Available options:
//@
//@ + `-c`: Clears the directory stack by deleting all of the elements.
//@
//@ Arguments:
//@
//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
//@
//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified.
//@
//@ See also: pushd, popd
function _dirs(options, index) {
if (_isStackIndex(options)) {
index = options;
options = '';
}
options = common.parseOptions(options, {
'c' : 'clear'
});
if (options['clear']) {
_dirStack = [];
return _dirStack;
}
var stack = _actualDirStack();
if (index) {
index = _parseStackIndex(index);
if (index < 0) {
index = stack.length + index;
}
common.log(stack[index]);
return stack[index];
}
common.log(stack.join(' '));
return stack;
}
exports.dirs = _dirs;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 1 1 1 | var common = require('./common');
//@
//@ ### echo(string [,string ...])
//@
//@ Examples:
//@
//@ ```javascript
//@ echo('hello world');
//@ var str = echo('hello world');
//@ ```
//@
//@ Prints string to stdout, and returns string with additional utility methods
//@ like `.to()`.
function _echo() {
var messages = [].slice.call(arguments, 0);
console.log.apply(this, messages);
return common.ShellString(messages.join(' '));
}
module.exports = _echo;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 | 1 1 1 | var common = require('./common');
//@
//@ ### error()
//@ Tests if error occurred in the last command. Returns `null` if no error occurred,
//@ otherwise returns string explaining the error
function error() {
return common.state.error;
};
module.exports = error;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | 1 1 1 1 1 1 1 1 1 1 1 1 | var common = require('./common');
var _tempDir = require('./tempdir');
var _pwd = require('./pwd');
var path = require('path');
var fs = require('fs');
var child = require('child_process');
// Hack to run child_process.exec() synchronously (sync avoids callback hell)
// Uses a custom wait loop that checks for a flag file, created when the child process is done.
// (Can't do a wait loop that checks for internal Node variables/messages as
// Node is single-threaded; callbacks and other internal state changes are done in the
// event loop).
function execSync(cmd, opts) {
var tempDir = _tempDir();
var stdoutFile = path.resolve(tempDir+'/'+common.randomFileName()),
codeFile = path.resolve(tempDir+'/'+common.randomFileName()),
scriptFile = path.resolve(tempDir+'/'+common.randomFileName()),
sleepFile = path.resolve(tempDir+'/'+common.randomFileName());
var options = common.extend({
silent: common.config.silent
}, opts);
var previousStdoutContent = '';
// Echoes stdout changes from running process, if not silent
function updateStdout() {
if (options.silent || !fs.existsSync(stdoutFile))
return;
var stdoutContent = fs.readFileSync(stdoutFile, 'utf8');
// No changes since last time?
if (stdoutContent.length <= previousStdoutContent.length)
return;
process.stdout.write(stdoutContent.substr(previousStdoutContent.length));
previousStdoutContent = stdoutContent;
}
function escape(str) {
return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0");
}
if (fs.existsSync(scriptFile)) common.unlinkSync(scriptFile);
if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile);
if (fs.existsSync(codeFile)) common.unlinkSync(codeFile);
var execCommand = '"'+process.execPath+'" '+scriptFile;
var execOptions = {
env: process.env,
cwd: _pwd(),
maxBuffer: 20*1024*1024
};
if (typeof child.execSync === 'function') {
var script = [
"var child = require('child_process')",
" , fs = require('fs');",
"var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {",
" fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');",
"});",
"var stdoutStream = fs.createWriteStream('"+escape(stdoutFile)+"');",
"childProcess.stdout.pipe(stdoutStream, {end: false});",
"childProcess.stderr.pipe(stdoutStream, {end: false});",
"childProcess.stdout.pipe(process.stdout);",
"childProcess.stderr.pipe(process.stderr);",
"var stdoutEnded = false, stderrEnded = false;",
"function tryClosing(){ if(stdoutEnded && stderrEnded){ stdoutStream.end(); } }",
"childProcess.stdout.on('end', function(){ stdoutEnded = true; tryClosing(); });",
"childProcess.stderr.on('end', function(){ stderrEnded = true; tryClosing(); });"
].join('\n');
fs.writeFileSync(scriptFile, script);
if (options.silent) {
execOptions.stdio = 'ignore';
} else {
execOptions.stdio = [0, 1, 2];
}
// Welcome to the future
child.execSync(execCommand, execOptions);
} else {
cmd += ' > '+stdoutFile+' 2>&1'; // works on both win/unix
var script = [
"var child = require('child_process')",
" , fs = require('fs');",
"var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {",
" fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');",
"});"
].join('\n');
fs.writeFileSync(scriptFile, script);
child.exec(execCommand, execOptions);
// The wait loop
// sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage
// (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing
// CPU usage, though apparently not so much on Windows)
while (!fs.existsSync(codeFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }
while (!fs.existsSync(stdoutFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); }
}
// At this point codeFile exists, but it's not necessarily flushed yet.
// Keep reading it until it is.
var code = parseInt('', 10);
while (isNaN(code)) {
code = parseInt(fs.readFileSync(codeFile, 'utf8'), 10);
}
var stdout = fs.readFileSync(stdoutFile, 'utf8');
// No biggie if we can't erase the files now -- they're in a temp dir anyway
try { common.unlinkSync(scriptFile); } catch(e) {}
try { common.unlinkSync(stdoutFile); } catch(e) {}
try { common.unlinkSync(codeFile); } catch(e) {}
try { common.unlinkSync(sleepFile); } catch(e) {}
// some shell return codes are defined as errors, per http://tldp.org/LDP/abs/html/exitcodes.html
if (code === 1 || code === 2 || code >= 126) {
common.error('', true); // unix/shell doesn't really give an error message after non-zero exit codes
}
// True if successful, false if not
var obj = {
code: code,
output: stdout
};
return obj;
} // execSync()
// Wrapper around exec() to enable echoing output to console in real time
function execAsync(cmd, opts, callback) {
var output = '';
var options = common.extend({
silent: common.config.silent
}, opts);
var c = child.exec(cmd, {env: process.env, maxBuffer: 20*1024*1024}, function(err) {
if (callback)
callback(err ? err.code : 0, output);
});
c.stdout.on('data', function(data) {
output += data;
if (!options.silent)
process.stdout.write(data);
});
c.stderr.on('data', function(data) {
output += data;
if (!options.silent)
process.stdout.write(data);
});
return c;
}
//@
//@ ### exec(command [, options] [, callback])
//@ Available options (all `false` by default):
//@
//@ + `async`: Asynchronous execution. Defaults to true if a callback is provided.
//@ + `silent`: Do not echo program output to console.
//@
//@ Examples:
//@
//@ ```javascript
//@ var version = exec('node --version', {silent:true}).output;
//@
//@ var child = exec('some_long_running_process', {async:true});
//@ child.stdout.on('data', function(data) {
//@ /* ... do something with data ... */
//@ });
//@
//@ exec('some_long_running_process', function(code, output) {
//@ console.log('Exit code:', code);
//@ console.log('Program output:', output);
//@ });
//@ ```
//@
//@ Executes the given `command` _synchronously_, unless otherwise specified.
//@ When in synchronous mode returns the object `{ code:..., output:... }`, containing the program's
//@ `output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and
//@ the `callback` gets the arguments `(code, output)`.
//@
//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as
//@ the current synchronous implementation uses a lot of CPU. This should be getting
//@ fixed soon.
function _exec(command, options, callback) {
if (!command)
common.error('must specify command');
// Callback is defined instead of options.
if (typeof options === 'function') {
callback = options;
options = { async: true };
}
// Callback is defined with options.
if (typeof options === 'object' && typeof callback === 'function') {
options.async = true;
}
options = common.extend({
silent: common.config.silent,
async: false
}, options);
if (options.async)
return execAsync(command, options, callback);
else
return execSync(command, options);
}
module.exports = _exec;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 1 1 1 1 1 1 | var fs = require('fs');
var common = require('./common');
var _ls = require('./ls');
//@
//@ ### find(path [,path ...])
//@ ### find(path_array)
//@ Examples:
//@
//@ ```javascript
//@ find('src', 'lib');
//@ find(['src', 'lib']); // same as above
//@ find('.').filter(function(file) { return file.match(/\.js$/); });
//@ ```
//@
//@ Returns array of all files (however deep) in the given paths.
//@
//@ The main difference from `ls('-R', path)` is that the resulting file names
//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`.
function _find(options, paths) {
if (!paths)
common.error('no path specified');
else if (typeof paths === 'object')
paths = paths; // assume array
else if (typeof paths === 'string')
paths = [].slice.call(arguments, 1);
var list = [];
function pushFile(file) {
if (common.platform === 'win')
file = file.replace(/\\/g, '/');
list.push(file);
}
// why not simply do ls('-R', paths)? because the output wouldn't give the base dirs
// to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory
paths.forEach(function(file) {
pushFile(file);
if (fs.statSync(file).isDirectory()) {
_ls('-RA', file+'/*').forEach(function(subfile) {
pushFile(subfile);
});
}
});
return list;
}
module.exports = _find;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 1 1 1 1 | var common = require('./common');
var fs = require('fs');
//@
//@ ### grep([options ,] regex_filter, file [, file ...])
//@ ### grep([options ,] regex_filter, file_array)
//@ Available options:
//@
//@ + `-v`: Inverse the sense of the regex and print the lines not matching the criteria.
//@
//@ Examples:
//@
//@ ```javascript
//@ grep('-v', 'GLOBAL_VARIABLE', '*.js');
//@ grep('GLOBAL_VARIABLE', '*.js');
//@ ```
//@
//@ Reads input string from given files and returns a string containing all lines of the
//@ file that match the given `regex_filter`. Wildcard `*` accepted.
function _grep(options, regex, files) {
options = common.parseOptions(options, {
'v': 'inverse'
});
if (!files)
common.error('no paths given');
if (typeof files === 'string')
files = [].slice.call(arguments, 2);
// if it's array leave it as it is
files = common.expand(files);
var grep = '';
files.forEach(function(file) {
if (!fs.existsSync(file)) {
common.error('no such file or directory: ' + file, true);
return;
}
var contents = fs.readFileSync(file, 'utf8'),
lines = contents.split(/\r*\n/);
lines.forEach(function(line) {
var matched = line.match(regex);
if ((options.inverse && !matched) || (!options.inverse && matched))
grep += line + '\n';
});
});
return common.ShellString(grep);
}
module.exports = _grep;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 1 1 1 1 1 1 | var fs = require('fs');
var path = require('path');
var common = require('./common');
var os = require('os');
//@
//@ ### ln(options, source, dest)
//@ ### ln(source, dest)
//@ Available options:
//@
//@ + `s`: symlink
//@ + `f`: force
//@
//@ Examples:
//@
//@ ```javascript
//@ ln('file', 'newlink');
//@ ln('-sf', 'file', 'existing');
//@ ```
//@
//@ Links source to dest. Use -f to force the link, should dest already exist.
function _ln(options, source, dest) {
options = common.parseOptions(options, {
's': 'symlink',
'f': 'force'
});
if (!source || !dest) {
common.error('Missing <source> and/or <dest>');
}
source = path.resolve(process.cwd(), String(source));
dest = path.resolve(process.cwd(), String(dest));
if (!fs.existsSync(source)) {
common.error('Source file does not exist', true);
}
if (fs.existsSync(dest)) {
if (!options.force) {
common.error('Destination file exists', true);
}
fs.unlinkSync(dest);
}
if (options.symlink) {
fs.symlinkSync(source, dest, os.platform() === "win32" ? "junction" : null);
} else {
fs.linkSync(source, dest, os.platform() === "win32" ? "junction" : null);
}
}
module.exports = _ln;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 1 1 1 1 1 1 1 1 | var path = require('path');
var fs = require('fs');
var common = require('./common');
var _cd = require('./cd');
var _pwd = require('./pwd');
//@
//@ ### ls([options ,] path [,path ...])
//@ ### ls([options ,] path_array)
//@ Available options:
//@
//@ + `-R`: recursive
//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`)
//@
//@ Examples:
//@
//@ ```javascript
//@ ls('projs/*.js');
//@ ls('-R', '/users/me', '/tmp');
//@ ls('-R', ['/users/me', '/tmp']); // same as above
//@ ```
//@
//@ Returns array of files in the given path, or in current directory if no path provided.
function _ls(options, paths) {
options = common.parseOptions(options, {
'R': 'recursive',
'A': 'all',
'a': 'all_deprecated'
});
if (options.all_deprecated) {
// We won't support the -a option as it's hard to image why it's useful
// (it includes '.' and '..' in addition to '.*' files)
// For backwards compatibility we'll dump a deprecated message and proceed as before
common.log('ls: Option -a is deprecated. Use -A instead');
options.all = true;
}
if (!paths)
paths = ['.'];
else if (typeof paths === 'object')
paths = paths; // assume array
else if (typeof paths === 'string')
paths = [].slice.call(arguments, 1);
var list = [];
// Conditionally pushes file to list - returns true if pushed, false otherwise
// (e.g. prevents hidden files to be included unless explicitly told so)
function pushFile(file, query) {
// hidden file?
if (path.basename(file)[0] === '.') {
// not explicitly asking for hidden files?
if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1))
return false;
}
if (common.platform === 'win')
file = file.replace(/\\/g, '/');
list.push(file);
return true;
}
paths.forEach(function(p) {
if (fs.existsSync(p)) {
var stats = fs.statSync(p);
// Simple file?
if (stats.isFile()) {
pushFile(p, p);
return; // continue
}
// Simple dir?
if (stats.isDirectory()) {
// Iterate over p contents
fs.readdirSync(p).forEach(function(file) {
if (!pushFile(file, p))
return;
// Recursive?
if (options.recursive) {
var oldDir = _pwd();
_cd('', p);
if (fs.statSync(file).isDirectory())
list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*'));
_cd('', oldDir);
}
});
return; // continue
}
}
// p does not exist - possible wildcard present
var basename = path.basename(p);
var dirname = path.dirname(p);
// Wildcard present on an existing dir? (e.g. '/tmp/*.js')
if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) {
// Escape special regular expression chars
var regexp = basename.replace(/(\^|\$|\(|\)|<|>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1');
// Translates wildcard into regex
regexp = '^' + regexp.replace(/\*/g, '.*') + '$';
// Iterate over directory contents
fs.readdirSync(dirname).forEach(function(file) {
if (file.match(new RegExp(regexp))) {
if (!pushFile(path.normalize(dirname+'/'+file), basename))
return;
// Recursive?
if (options.recursive) {
var pp = dirname + '/' + file;
if (fs.lstatSync(pp).isDirectory())
list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*'));
} // recursive
} // if file matches
}); // forEach
return;
}
common.error('no such file or directory: ' + p, true);
});
return list;
}
module.exports = _ls;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | 1 1 1 1 1 1 | var common = require('./common');
var fs = require('fs');
var path = require('path');
// Recursively creates 'dir'
function mkdirSyncRecursive(dir) {
var baseDir = path.dirname(dir);
// Base dir exists, no recursion necessary
if (fs.existsSync(baseDir)) {
fs.mkdirSync(dir, parseInt('0777', 8));
return;
}
// Base dir does not exist, go recursive
mkdirSyncRecursive(baseDir);
// Base dir created, can create dir
fs.mkdirSync(dir, parseInt('0777', 8));
}
//@
//@ ### mkdir([options ,] dir [, dir ...])
//@ ### mkdir([options ,] dir_array)
//@ Available options:
//@
//@ + `p`: full path (will create intermediate dirs if necessary)
//@
//@ Examples:
//@
//@ ```javascript
//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');
//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above
//@ ```
//@
//@ Creates directories.
function _mkdir(options, dirs) {
options = common.parseOptions(options, {
'p': 'fullpath'
});
if (!dirs)
common.error('no paths given');
if (typeof dirs === 'string')
dirs = [].slice.call(arguments, 1);
// if it's array leave it as it is
dirs.forEach(function(dir) {
if (fs.existsSync(dir)) {
if (!options.fullpath)
common.error('path already exists: ' + dir, true);
return; // skip dir
}
// Base dir does not exist, and no -p option given
var baseDir = path.dirname(dir);
if (!fs.existsSync(baseDir) && !options.fullpath) {
common.error('no such file or directory: ' + baseDir, true);
return; // skip dir
}
if (options.fullpath)
mkdirSyncRecursive(dir);
else
fs.mkdirSync(dir, parseInt('0777', 8));
});
} // mkdir
module.exports = _mkdir;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 1 1 1 1 1 | var fs = require('fs');
var path = require('path');
var common = require('./common');
//@
//@ ### mv(source [, source ...], dest')
//@ ### mv(source_array, dest')
//@ Available options:
//@
//@ + `f`: force
//@
//@ Examples:
//@
//@ ```javascript
//@ mv('-f', 'file', 'dir/');
//@ mv('file1', 'file2', 'dir/');
//@ mv(['file1', 'file2'], 'dir/'); // same as above
//@ ```
//@
//@ Moves files. The wildcard `*` is accepted.
function _mv(options, sources, dest) {
options = common.parseOptions(options, {
'f': 'force'
});
// Get sources, dest
if (arguments.length < 3) {
common.error('missing <source> and/or <dest>');
} else if (arguments.length > 3) {
sources = [].slice.call(arguments, 1, arguments.length - 1);
dest = arguments[arguments.length - 1];
} else if (typeof sources === 'string') {
sources = [sources];
} else if ('length' in sources) {
sources = sources; // no-op for array
} else {
common.error('invalid arguments');
}
sources = common.expand(sources);
var exists = fs.existsSync(dest),
stats = exists && fs.statSync(dest);
// Dest is not existing dir, but multiple sources given
if ((!exists || !stats.isDirectory()) && sources.length > 1)
common.error('dest is not a directory (too many sources)');
// Dest is an existing file, but no -f given
if (exists && stats.isFile() && !options.force)
common.error('dest file already exists: ' + dest);
sources.forEach(function(src) {
if (!fs.existsSync(src)) {
common.error('no such file or directory: '+src, true);
return; // skip file
}
// If here, src exists
// When copying to '/path/dir':
// thisDest = '/path/dir/file1'
var thisDest = dest;
if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
thisDest = path.normalize(dest + '/' + path.basename(src));
if (fs.existsSync(thisDest) && !options.force) {
common.error('dest file already exists: ' + thisDest, true);
return; // skip file
}
if (path.resolve(src) === path.dirname(path.resolve(thisDest))) {
common.error('cannot move to self: '+src, true);
return; // skip file
}
fs.renameSync(src, thisDest);
}); // forEach(src)
} // mv
module.exports = _mv;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | 1 1 1 1 | var path = require('path');
var common = require('./common');
//@
//@ ### pwd()
//@ Returns the current directory.
function _pwd(options) {
var pwd = path.resolve(process.cwd());
return common.ShellString(pwd);
}
module.exports = _pwd;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | 1 1 1 1 1 1 | var common = require('./common');
var fs = require('fs');
// Recursively removes 'dir'
// Adapted from https://github.com/ryanmcgrath/wrench-js
//
// Copyright (c) 2010 Ryan McGrath
// Copyright (c) 2012 Artur Adib
//
// Licensed under the MIT License
// http://www.opensource.org/licenses/mit-license.php
function rmdirSyncRecursive(dir, force) {
var files;
files = fs.readdirSync(dir);
// Loop through and delete everything in the sub-tree after checking it
for(var i = 0; i < files.length; i++) {
var file = dir + "/" + files[i],
currFile = fs.lstatSync(file);
if(currFile.isDirectory()) { // Recursive function back to the beginning
rmdirSyncRecursive(file, force);
}
else if(currFile.isSymbolicLink()) { // Unlink symlinks
if (force || isWriteable(file)) {
try {
common.unlinkSync(file);
} catch (e) {
common.error('could not remove file (code '+e.code+'): ' + file, true);
}
}
}
else // Assume it's a file - perhaps a try/catch belongs here?
if (force || isWriteable(file)) {
try {
common.unlinkSync(file);
} catch (e) {
common.error('could not remove file (code '+e.code+'): ' + file, true);
}
}
}
// Now that we know everything in the sub-tree has been deleted, we can delete the main directory.
// Huzzah for the shopkeep.
var result;
try {
// Retry on windows, sometimes it takes a little time before all the files in the directory are gone
var start = Date.now();
while (true) {
try {
result = fs.rmdirSync(dir);
if (fs.existsSync(dir)) throw { code: "EAGAIN" }
break;
} catch(er) {
// In addition to error codes, also check if the directory still exists and loop again if true
if (process.platform === "win32" && (er.code === "ENOTEMPTY" || er.code === "EBUSY" || er.code === "EPERM" || er.code === "EAGAIN")) {
if (Date.now() - start > 1000) throw er;
} else if (er.code === "ENOENT") {
// Directory did not exist, deletion was successful
break;
} else {
throw er;
}
}
}
} catch(e) {
common.error('could not remove directory (code '+e.code+'): ' + dir, true);
}
return result;
} // rmdirSyncRecursive
// Hack to determine if file has write permissions for current user
// Avoids having to check user, group, etc, but it's probably slow
function isWriteable(file) {
var writePermission = true;
try {
var __fd = fs.openSync(file, 'a');
fs.closeSync(__fd);
} catch(e) {
writePermission = false;
}
return writePermission;
}
//@
//@ ### rm([options ,] file [, file ...])
//@ ### rm([options ,] file_array)
//@ Available options:
//@
//@ + `-f`: force
//@ + `-r, -R`: recursive
//@
//@ Examples:
//@
//@ ```javascript
//@ rm('-rf', '/tmp/*');
//@ rm('some_file.txt', 'another_file.txt');
//@ rm(['some_file.txt', 'another_file.txt']); // same as above
//@ ```
//@
//@ Removes files. The wildcard `*` is accepted.
function _rm(options, files) {
options = common.parseOptions(options, {
'f': 'force',
'r': 'recursive',
'R': 'recursive'
});
if (!files)
common.error('no paths given');
if (typeof files === 'string')
files = [].slice.call(arguments, 1);
// if it's array leave it as it is
files = common.expand(files);
files.forEach(function(file) {
if (!fs.existsSync(file)) {
// Path does not exist, no force flag given
if (!options.force)
common.error('no such file or directory: '+file, true);
return; // skip file
}
// If here, path exists
var stats = fs.lstatSync(file);
if (stats.isFile() || stats.isSymbolicLink()) {
// Do not check for file writing permissions
if (options.force) {
common.unlinkSync(file);
return;
}
if (isWriteable(file))
common.unlinkSync(file);
else
common.error('permission denied: '+file, true);
return;
} // simple file
// Path is an existing directory, but no -r flag given
if (stats.isDirectory() && !options.recursive) {
common.error('path is a directory', true);
return; // skip path
}
// Recursively remove existing directory
if (stats.isDirectory() && options.recursive) {
rmdirSyncRecursive(file, options.force);
}
}); // forEach(file)
} // rm
module.exports = _rm;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 1 1 1 1 | var common = require('./common');
var fs = require('fs');
//@
//@ ### sed([options ,] search_regex, replacement, file)
//@ Available options:
//@
//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
//@
//@ Examples:
//@
//@ ```javascript
//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');
//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js');
//@ ```
//@
//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input
//@ using the given search regex and replacement string or function. Returns the new string after replacement.
function _sed(options, regex, replacement, file) {
options = common.parseOptions(options, {
'i': 'inplace'
});
if (typeof replacement === 'string' || typeof replacement === 'function')
replacement = replacement; // no-op
else if (typeof replacement === 'number')
replacement = replacement.toString(); // fallback
else
common.error('invalid replacement string');
if (!file)
common.error('no file given');
if (!fs.existsSync(file))
common.error('no such file or directory: ' + file);
var result = fs.readFileSync(file, 'utf8').replace(regex, replacement);
if (options.inplace)
fs.writeFileSync(file, result, 'utf8');
return common.ShellString(result);
}
module.exports = _sed;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | 1 1 1 1 1 1 | var common = require('./common');
var os = require('os');
var fs = require('fs');
// Returns false if 'dir' is not a writeable directory, 'dir' otherwise
function writeableDir(dir) {
if (!dir || !fs.existsSync(dir))
return false;
if (!fs.statSync(dir).isDirectory())
return false;
var testFile = dir+'/'+common.randomFileName();
try {
fs.writeFileSync(testFile, ' ');
common.unlinkSync(testFile);
return dir;
} catch (e) {
return false;
}
}
//@
//@ ### tempdir()
//@
//@ Examples:
//@
//@ ```javascript
//@ var tmp = tempdir(); // "/tmp" for most *nix platforms
//@ ```
//@
//@ Searches and returns string containing a writeable, platform-dependent temporary directory.
//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).
function _tempDir() {
var state = common.state;
if (state.tempDir)
return state.tempDir; // from cache
state.tempDir = writeableDir(os.tempDir && os.tempDir()) || // node 0.8+
writeableDir(process.env['TMPDIR']) ||
writeableDir(process.env['TEMP']) ||
writeableDir(process.env['TMP']) ||
writeableDir(process.env['Wimp$ScrapDir']) || // RiscOS
writeableDir('C:\\TEMP') || // Windows
writeableDir('C:\\TMP') || // Windows
writeableDir('\\TEMP') || // Windows
writeableDir('\\TMP') || // Windows
writeableDir('/tmp') ||
writeableDir('/var/tmp') ||
writeableDir('/usr/tmp') ||
writeableDir('.'); // last resort
return state.tempDir;
}
module.exports = _tempDir;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | 1 1 1 1 | var common = require('./common');
var fs = require('fs');
//@
//@ ### test(expression)
//@ Available expression primaries:
//@
//@ + `'-b', 'path'`: true if path is a block device
//@ + `'-c', 'path'`: true if path is a character device
//@ + `'-d', 'path'`: true if path is a directory
//@ + `'-e', 'path'`: true if path exists
//@ + `'-f', 'path'`: true if path is a regular file
//@ + `'-L', 'path'`: true if path is a symboilc link
//@ + `'-p', 'path'`: true if path is a pipe (FIFO)
//@ + `'-S', 'path'`: true if path is a socket
//@
//@ Examples:
//@
//@ ```javascript
//@ if (test('-d', path)) { /* do something with dir */ };
//@ if (!test('-f', path)) continue; // skip if it's a regular file
//@ ```
//@
//@ Evaluates expression using the available primaries and returns corresponding value.
function _test(options, path) {
if (!path)
common.error('no path given');
// hack - only works with unary primaries
options = common.parseOptions(options, {
'b': 'block',
'c': 'character',
'd': 'directory',
'e': 'exists',
'f': 'file',
'L': 'link',
'p': 'pipe',
'S': 'socket'
});
var canInterpret = false;
for (var key in options)
if (options[key] === true) {
canInterpret = true;
break;
}
if (!canInterpret)
common.error('could not interpret expression');
if (options.link) {
try {
return fs.lstatSync(path).isSymbolicLink();
} catch(e) {
return false;
}
}
if (!fs.existsSync(path))
return false;
if (options.exists)
return true;
var stats = fs.statSync(path);
if (options.block)
return stats.isBlockDevice();
if (options.character)
return stats.isCharacterDevice();
if (options.directory)
return stats.isDirectory();
if (options.file)
return stats.isFile();
if (options.pipe)
return stats.isFIFO();
if (options.socket)
return stats.isSocket();
} // test
module.exports = _test;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 1 1 1 1 1 | var common = require('./common');
var fs = require('fs');
var path = require('path');
//@
//@ ### 'string'.to(file)
//@
//@ Examples:
//@
//@ ```javascript
//@ cat('input.txt').to('output.txt');
//@ ```
//@
//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as
//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_
function _to(options, file) {
if (!file)
common.error('wrong arguments');
if (!fs.existsSync( path.dirname(file) ))
common.error('no such file or directory: ' + path.dirname(file));
try {
fs.writeFileSync(file, this.toString(), 'utf8');
} catch(e) {
common.error('could not write to file (code '+e.code+'): '+file, true);
}
}
module.exports = _to;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 1 1 1 1 1 | var common = require('./common');
var fs = require('fs');
var path = require('path');
//@
//@ ### 'string'.toEnd(file)
//@
//@ Examples:
//@
//@ ```javascript
//@ cat('input.txt').toEnd('output.txt');
//@ ```
//@
//@ Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaScript strings (such as
//@ those returned by `cat`, `grep`, etc).
function _toEnd(options, file) {
if (!file)
common.error('wrong arguments');
if (!fs.existsSync( path.dirname(file) ))
common.error('no such file or directory: ' + path.dirname(file));
try {
fs.appendFileSync(file, this.toString(), 'utf8');
} catch(e) {
common.error('could not append to file (code '+e.code+'): '+file, true);
}
}
module.exports = _toEnd;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | 1 1 1 1 1 1 1 | var common = require('./common');
var fs = require('fs');
var path = require('path');
// Cross-platform method for splitting environment PATH variables
function splitPath(p) {
for (i=1;i<2;i++) {}
if (!p)
return [];
if (common.platform === 'win')
return p.split(';');
else
return p.split(':');
}
function checkPath(path) {
return fs.existsSync(path) && fs.statSync(path).isDirectory() == false;
}
//@
//@ ### which(command)
//@
//@ Examples:
//@
//@ ```javascript
//@ var nodeExec = which('node');
//@ ```
//@
//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.
//@ Returns string containing the absolute path to the command.
function _which(options, cmd) {
if (!cmd)
common.error('must specify command');
var pathEnv = process.env.path || process.env.Path || process.env.PATH,
pathArray = splitPath(pathEnv),
where = null;
// No relative/absolute paths provided?
if (cmd.search(/\//) === -1) {
// Search for command in PATH
pathArray.forEach(function(dir) {
if (where)
return; // already found it
var attempt = path.resolve(dir + '/' + cmd);
if (checkPath(attempt)) {
where = attempt;
return;
}
if (common.platform === 'win') {
var baseAttempt = attempt;
attempt = baseAttempt + '.exe';
if (checkPath(attempt)) {
where = attempt;
return;
}
attempt = baseAttempt + '.cmd';
if (checkPath(attempt)) {
where = attempt;
return;
}
attempt = baseAttempt + '.bat';
if (checkPath(attempt)) {
where = attempt;
return;
}
} // if 'win'
});
}
// Command not found anywhere?
if (!checkPath(cmd) && !where)
return null;
where = where || path.resolve(cmd);
return common.ShellString(where);
}
module.exports = _which;
|
| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| analytics-loader.js | 28.38% | (21 / 74) | 9.09% | (3 / 33) | 8.33% | (1 / 12) | 28.38% | (21 / 74) | |
| analytics.js | 60% | (18 / 30) | 44.44% | (4 / 9) | 25% | (1 / 4) | 60% | (18 / 30) | |
| before-plugin-add.js | 22.22% | (4 / 18) | 0% | (0 / 2) | 0% | (0 / 5) | 23.53% | (4 / 17) | |
| cca.js | 14.88% | (18 / 121) | 1.92% | (1 / 52) | 0% | (0 / 26) | 14.88% | (18 / 121) | |
| cordova-commands.js | 21.05% | (4 / 19) | 0% | (0 / 6) | 0% | (0 / 5) | 21.05% | (4 / 19) | |
| create-app.js | 8.91% | (9 / 101) | 0% | (0 / 44) | 0% | (0 / 19) | 9.09% | (9 / 99) | |
| default-config.js | 37.5% | (3 / 8) | 0% | (0 / 2) | 0% | (0 / 1) | 37.5% | (3 / 8) | |
| exec.js | 33.33% | (4 / 12) | 0% | (0 / 2) | 0% | (0 / 2) | 33.33% | (4 / 12) | |
| get-manifest.js | 66.67% | (6 / 9) | 100% | (0 / 0) | 0% | (0 / 2) | 66.67% | (6 / 9) | |
| hooks.js | 66.67% | (12 / 18) | 100% | (0 / 0) | 0% | (0 / 2) | 66.67% | (12 / 18) | |
| parse-command-line.js | 60% | (3 / 5) | 100% | (0 / 0) | 0% | (0 / 1) | 60% | (3 / 5) | |
| post-prepare.js | 16.98% | (9 / 53) | 0% | (0 / 18) | 0% | (0 / 10) | 17.65% | (9 / 51) | |
| pre-prepare.js | 12.64% | (11 / 87) | 0% | (0 / 29) | 0% | (0 / 9) | 12.79% | (11 / 86) | |
| push-to-harness.js | 14.88% | (18 / 121) | 2.08% | (1 / 48) | 0% | (0 / 28) | 14.88% | (18 / 121) | |
| run-in-chrome.js | 22.73% | (5 / 22) | 0% | (0 / 14) | 0% | (0 / 2) | 22.73% | (5 / 22) | |
| tools-check.js | 25.71% | (9 / 35) | 0% | (0 / 8) | 0% | (0 / 17) | 25.71% | (9 / 35) | |
| upgrade-project.js | 20.83% | (15 / 72) | 0% | (0 / 26) | 0% | (0 / 14) | 21.13% | (15 / 71) | |
| utils.js | 21.82% | (12 / 55) | 0% | (0 / 18) | 0% | (0 / 13) | 22.22% | (12 / 54) | |
| write-out-cca-version.js | 50% | (4 / 8) | 0% | (0 / 2) | 0% | (0 / 1) | 50% | (4 / 8) |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | var Q = require('q');
var path = require('path');
var fs = require('fs');
var shelljs = require('shelljs');
var utils = require('./utils');
var analyticsModule;
// This function retrieves either the analytics module or a mocked version that provides no-ops.
// If the argument is true, the mocked version will log all calls.
function getAnalyticsModule(useTestingVersion) {
if (useTestingVersion) {
analyticsModule = makeFakeModule(true /* logCalls */);
return Q(analyticsModule);
}
// If we've already loaded an analytics module, use the one we already have.
if (analyticsModule) {
return Q(analyticsModule);
}
// Ask for permission and return a module accordingly.
return requestPermission()
.then(function(permission) {
analyticsModule = permission ? require('./analytics') : makeFakeModule(false /* logCalls */);
return Q(analyticsModule);
});
}
// This function returns a fake analytics module.
// If the argument is true, the fake module will log all calls.
function makeFakeModule(logCalls) {
var fakeModule = { };
// These "functions to fake" should be updated whenever a function is added to the real analytics module.
var funcsToFake = ['sendEvent'];
// Fake our functions, logging if required.
funcsToFake.forEach(function(f) {
if (logCalls) {
fakeModule[f] = function() {
log({ func: f, args: arguments });
};
} else {
fakeModule[f] = function() { };
}
});
return fakeModule;
}
// This function determines whether the developer approves of the collection of usage statistics.
// If permission has previously been ascertained, we read it from a file. Otherwise, we the user now.
// It returns a promise that contains the answer.
function requestPermission() {
// Load the config file and check if permission has already been granted or denied.
var userConfig = readWriteUserConfig();
if (userConfig && userConfig.analytics) {
return Q(userConfig.analytics.isAllowed);
}
// We have no record of permission, so ask away.
var promptText = 'Would you like to help make make this tool better by automatically sending usage statistics and error reports to Google?\n';
promptText += 'This information will be used in accordance with the Google Privacy Policy (http://www.google.com/policies/privacy). [y/n] ';
return utils.waitForKey(promptText)
.then(function(key) {
var permission = (key.toLowerCase() == 'y');
// Write the response to the config file and return it.
writePermission(permission);
return permission;
});
}
// This function writes the given permission to the config file.
function writePermission(permission) {
var userConfig = readWriteUserConfig();
userConfig = userConfig || {};
userConfig.analytics = userConfig.analytics || {};
userConfig.analytics.isAllowed = permission;
userConfig.analytics.savedOnDate = new Date();
readWriteUserConfig(userConfig);
}
// This function either reads or writes the config file.
// If the argument is empty, this function reads the returns the config file.
// If the argument is not empty, its contents are written to the config file.
function readWriteUserConfig(userConfig) {
// Determine the path of the config file.
// We use this format to comply with the `rc` config loader (https://github.com/dominictarr/rc), in case we use that in the future.
var HOME = process.env[(process.platform.slice(0, 3) == 'win') ? 'USERPROFILE' : 'HOME'];
var userConfigDir = path.join(HOME, '.cca');
var userConfigPath = path.join(userConfigDir, 'config');
// Write to the file if we were passed an argument, or read and return it if we were.
// If we were instructed to read the file, but it doesn't exist, return null.
Iif (userConfig) {
shelljs.mkdir('-p', userConfigDir);
fs.writeFileSync(userConfigPath, JSON.stringify(userConfig, null, 4));
} else Eif (fs.existsSync(userConfigPath)) {
userConfig = JSON.parse(fs.readFileSync(userConfigPath, 'utf-8'));
return userConfig;
} else {
return null;
}
}
// This function handles calls to `cca analytics`.
function analyticsCommand(command) {
var usage = '`cca analytics [enable|disable]`';
// `cca analytics` will tell the user whether analytics are enabled or disabled.
if (!command) {
var userConfig = readWriteUserConfig();
var permission = userConfig && userConfig.analytics && userConfig.analytics.isAllowed;
var outputText = 'Usage statistics collection is currently ' + (permission ? 'enabled' : 'disabled') + '. ';
outputText += 'To change this, run ' + usage + '.';
console.log(outputText);
return;
}
// We only allow `enable` and `disable`; print an error if we were given something else.
command = command.toLowerCase();
if (command != 'enable' && command != 'disable') {
var errorText = 'Invalid argument: ' + command + '. ';
errorText += 'To enable or disable usage statistics collection, run ' + usage + '.';
utils.fatal(errorText);
return;
}
// Set analytics permission according to the given command.
writePermission(command == 'enable');
console.log('Usage statistics collection ' + command + 'd.');
}
// This function prints the given object, along with a timestamp.
function log(x) {
var now = new Date();
x.timestamp = now.toISOString();
console.log(JSON.stringify(x));
}
// Exports!
module.exports = {
analyticsCommand: analyticsCommand,
getAnalyticsModule: getAnalyticsModule,
readWriteUserConfig: readWriteUserConfig
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
// Common parameters.
var v = 1; // Protocol version.
var tid = 'UA-52080037-2'; // Tracking ID.
var cid = getClientId(); // Client ID.
var an = 'cca'; // App name.
var av = require('../package').version; // App version.
// URL base, based on the above parameters.
var URL_BASE = 'http://www.google-analytics.com/collect?';
URL_BASE += 'v=' + v;
URL_BASE += '&tid=' + tid;
URL_BASE += '&cid=' + cid;
URL_BASE += '&an=' + an;
URL_BASE += '&av=' + av;
// This function retrieves the client ID from the config file or generates if it one doesn't exist.
function getClientId() {
var analyticsLoader = require('./analytics-loader');
var userConfig = analyticsLoader.readWriteUserConfig();
// Return the client id from the file, if one is there.
Eif (userConfig && userConfig.analytics && userConfig.analytics.clientId) {
return userConfig.analytics.clientId;
}
// We don't have a client id yet, so generate one, save it, and return it.
userConfig = userConfig || {};
userConfig.analytics = userConfig.analytics || {};
userConfig.analytics.clientId = require('node-uuid').v4();
analyticsLoader.readWriteUserConfig(userConfig);
return userConfig.analytics.clientId;
}
// This helper function sends a measurement to the given URL.
function sendMeasurement(url) {
// On an error, silently fail.
// TODO(maxw): Queue and retry failed measurements.
var http = require('http');
http.get(url).on('error', function() { });
}
module.exports = {
// Send an event to the analytics server.
sendEvent: function(eventCategory, eventAction) {
var url = URL_BASE;
url += '&t=event';
url += '&ec=' + eventCategory;
url += '&ea=' + eventAction;
sendMeasurement(url);
}
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
'use strict';
var getManifest = require('./get-manifest');
var ccaManifestLogic = require('cca-manifest-logic');
var Q = require('q');
// Returns a promise.
module.exports = exports = function beforePluginAdd(context) {
return getManifest('www')
.then(function(manifest) {
return ccaManifestLogic.analyseManifest(manifest);
})
.then(function(manifestData) {
var pluginsToBeNotInstalled = manifestData.pluginsToBeNotInstalled.concat();
var pluginsBeingInstalledRightNow = context.plugins;
pluginsToBeNotInstalled = pluginsToBeNotInstalled.filter(function(plugin) {
return pluginsBeingInstalledRightNow.indexOf(plugin) != -1;
});
if (pluginsToBeNotInstalled.length === 0) return;
console.error("Error: The following plugin(s) cannot be explicitly installed:");
pluginsToBeNotInstalled.forEach(function(plugin) {
console.warn("*", plugin);
});
console.error("Instead, add the proper manifest.json permissions.");
console.error("See: https://developer.chrome.com/apps/manifest");
return Q.reject("Abort plugin add");
});
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | //#!/usr/bin/env node
/**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
// System modules.
var fs = require('fs');
var path = require('path');
// Third-party modules.
var Q = require('q');
var updateNotifier = require('update-notifier');
// Local modules.
var utils = require('./utils');
// Globals
var origDir = process.cwd();
var ccaRoot = path.join(__dirname, '..');
var cordova = require('cordova');
var cordovaLib = cordova.cordova_lib;
var hooks = require('./hooks');
function main() {
cordovaLib.binname = 'cca';
var commandLineFlags = require('./parse-command-line')();
utils.exit.pause_on_exit = commandLineFlags.pause_on_exit;
// TODO: Should we support an opt out `--no-update-notifier`?
var pkg = require('../package.json');
updateNotifier({
pkg: pkg,
updateCheckInterval: 1000 * 60 * 60 * 24, // Daily
}).notify();
var command = commandLineFlags._[0];
var packageVersion = require('../package').version;
// Colorize after parseCommandLine to avoid --help being printed in red.
utils.colorizeConsole();
hooks.registerHooks();
function printCcaVersionPrefix() {
console.log('cca v' + packageVersion);
}
if (command == 'exec') {
return require('./tools-check').fixEnv()
.then(function() {
require('./exec')(process.argv.slice(3));
}).done(null, utils.fatal);
}
if (commandLineFlags.v) {
command = 'version';
}
if (commandLineFlags.h || !command) {
command = 'help';
}
function autoAddPlatforms() {
var plats = [];
if (process.argv.indexOf('android') != -1 && !fs.existsSync(path.join('platforms', 'android'))) {
plats.push('android');
}
if (process.argv.indexOf('ios') != -1 && !fs.existsSync(path.join('platforms', 'ios'))) {
plats.push('ios');
}
if (plats.length === 0) {
return Q();
}
var argv = require('optimist')
.options('link', { type: 'boolean' })
.options('verbose', { type: 'boolean', alias: 'd' })
.argv;
var opts = {
link: argv.link,
verbose: argv.verbose
};
return require('./cordova-commands').runCmd(['platform', 'add', plats, opts])
.then(require('./write-out-cca-version'));
}
function beforeCordovaPrepare() {
return autoAddPlatforms()
.then(function() {
if (commandLineFlags['skip-upgrade']) {
return;
}
if (!fs.existsSync(path.join('www', 'manifest.json'))) {
return Q.reject('This is not a cca project (no www/manifest.json file). Perhaps you meant to use the cordova-cli?');
}
return require('./upgrade-project').upgradeProjectIfStale(commandLineFlags.y);
});
}
function forwardCurrentCommandToCordova() {
// Unregister some event handlers in cordova-lib EventEmitter. Otherwise
// double printouts will happen because cordova-cli registers its own
// handlers. This is only relevant when --verbose or -d flag is used.
cordovaLib.events.removeListener('results', console.log);
cordovaLib.events.removeListener('log', console.log);
cordovaLib.events.removeListener('warn', console.warn);
cordovaLib.events.removeListener('verbose', console.log);
// TODO: Can we replace use of CLI here? Calls to cordova-lib cordova.raw?
return cordova.cli(process.argv);
}
function printVersionThenPrePrePrepareThenForwardCommandToCordova() {
printCcaVersionPrefix();
return beforeCordovaPrepare()
.then(forwardCurrentCommandToCordova);
}
var commandActions = {
'pre-prepare': function() {
return require('./pre-prepare')();
},
'update-app': function() {
// TODO: deprecated command, use post-prepare instead
return commandActions['post-prepare']();
},
'post-prepare': function() {
return require('./post-prepare')();
},
'checkenv': function() {
printCcaVersionPrefix();
return require('./tools-check')();
},
'push': function() {
printCcaVersionPrefix();
return Q.fcall(function() {
var extraFlag = commandLineFlags._[1] || '';
if (extraFlag) {
require('optimist').showHelp(console.log);
return Q.reject('Flag "' + extraFlag + '" not understood. Did you mean `--target=' + extraFlag + '`?');
}
return require('./push-to-harness')(commandLineFlags.target, commandLineFlags.watch);
});
},
'run': function() {
printCcaVersionPrefix();
var platform = commandLineFlags._[1];
if (platform === 'chrome' || platform === 'canary') {
return require('./run-in-chrome')(platform);
} else {
return beforeCordovaPrepare()
.then(forwardCurrentCommandToCordova);
}
},
'create': function() {
printCcaVersionPrefix();
return Q.fcall(function() {
var destAppDir = commandLineFlags._[1] || '';
if (!destAppDir) {
require('optimist').showHelp(console.log);
return Q.reject('No output directory given.');
}
// resolve turns relative paths into absolute
destAppDir = path.resolve(destAppDir);
var packageId = commandLineFlags._[2] || '';
var appName = commandLineFlags._[3] || '';
return require('./create-app')(destAppDir, ccaRoot, origDir, packageId, appName, commandLineFlags);
});
},
'upgrade': function() {
printCcaVersionPrefix();
return require('./upgrade-project').upgradeProject(true); // true means never prompt for upgrade
},
'version': function() {
console.log(packageVersion);
return Q.when();
},
'help': function() {
printCcaVersionPrefix();
require('optimist').showHelp(console.log);
return Q.when();
},
'plugin': printVersionThenPrePrePrepareThenForwardCommandToCordova,
'plugins': function() {
return commandActions.plugin.apply(this, arguments);
},
'platform': function() {
printCcaVersionPrefix();
// Do not run auto-upgrade step if doing a platforms command
return forwardCurrentCommandToCordova();
},
'platforms': function() {
return commandActions.platform.apply(this, arguments);
},
'analytics': function() {
// Do nothing. This is handled as a special-case below.
return Q.when();
},
'build': printVersionThenPrePrePrepareThenForwardCommandToCordova,
'compile': printVersionThenPrePrePrepareThenForwardCommandToCordova,
'emulate': printVersionThenPrePrePrepareThenForwardCommandToCordova,
'prepare': printVersionThenPrePrePrepareThenForwardCommandToCordova,
'serve': printVersionThenPrePrePrepareThenForwardCommandToCordova,
};
// TODO(mmocny): The following few lines seem to make global changes that affect all other subcommands.
// May want to break this out to a module as an "init" step that every other step ensures has been called.
cordovaLib.cordova.config.setAutoPersist(false);
var projectRoot = cordovaLib.cordova.findProjectRoot();
if (projectRoot) {
cordovaLib.cordova.config(projectRoot, require('./default-config')(ccaRoot));
process.chdir(projectRoot);
}
if (!commandActions.hasOwnProperty(command)) {
utils.fatal('Invalid command: ' + command + '. Use --help for usage.');
}
// In verbose mode, print all cordova events
if (commandLineFlags.d) {
// TODO: its possible we want to console.log the results for some cordova commands even in non-verbose mode
cordovaLib.events.on('results', console.log);
cordovaLib.events.on('log', console.log);
cordovaLib.events.on('warn', console.warn);
cordovaLib.events.on('verbose', console.log);
}
// If the command is an analytics command, act accordingly.
// We do this now because it's a special case. If this is the user's first command, a prompt doesn't make sense.
var analyticsLoader = require('./analytics-loader');
if (command === 'analytics') {
analyticsLoader.analyticsCommand(commandLineFlags._[1]);
}
if (commandLineFlags['android-minSdkVersion']) {
process.env['ORG_GRADLE_PROJECT_cdvMinSdkVersion'] = commandLineFlags['android-minSdkVersion'];
}
analyticsLoader.getAnalyticsModule()
.then(function(analytics) {
analytics.sendEvent('cca', command);
}).then(commandActions[command])
.then(null, function(e) {
if (e instanceof cordovaLib.CordovaError) {
utils.fatal(e.message.replace(/\bcordova /, 'cca '));
} else {
throw e;
}
}).done();
}
Iif (require.main === module) {
main();
} else {
module.exports.parseCLI = main;
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var cordova = require('cordova');
var Q = require('q');
// Returns the promise from the raw Cordova command.
exports.runCmd = function runCmd(cmd) {
var msg = cmd[0];
cmd.slice(1).forEach(function(arg) {
if (Array.isArray(arg)) {
msg += ' ' + arg.join(' ');
return;
} else if (typeof arg != 'string') {
return;
}
if (arg.indexOf(' ') != -1) {
msg += ' "' + arg + '"';
} else {
msg += ' ' + arg;
}
});
console.log('## Running Cordova Command: ' + msg);
return cordova.raw[cmd[0]].apply(cordova, cmd.slice(1));
};
// Chains a list of cordova commands, returning a promise.
exports.runAllCmds = function runAllCmds(commands) {
return commands.reduce(function(soFar, f) {
return soFar.then(function() {
return exports.runCmd(f);
});
}, Q());
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | 1 1 1 1 1 1 1 1 1 | var path = require('path');
var Q = require('q');
var fs = require('fs');
var shelljs = require('shelljs');
var xmldom = require('xmldom');
var ccaManifestLogic = require('cca-manifest-logic');
function resolveTilde(string) {
// TODO: implement better
if (string.substr(0,1) === '~')
return path.resolve(process.env.HOME + string.substr(1));
return string;
}
// Returns a promise
module.exports = exports = function createApp(destAppDir, ccaRoot, origDir, packageId, appName, flags) {
var srcAppDir = null;
var manifest = null;
var appWasImported = false;
var manifestDesktopFilename = path.join(destAppDir, 'www', 'manifest.json');
var manifestMobileFilename = path.join(destAppDir, 'www', 'manifest.mobile.json');
return Q.fcall(function() {
// Validate source arg.
var sourceArg = flags['copy-from'] || flags['link-to'];
appWasImported = !!sourceArg;
if (!sourceArg) {
srcAppDir = path.join(ccaRoot, 'templates', 'default-app');
} else {
// Strip off manifest.json from path (its containing dir must be the root of the app)
if (path.basename(sourceArg) === 'manifest.json') {
sourceArg = path.dirname(sourceArg);
}
// Always check the sourceArg as a relative path first, even if its a special value (like 'spec')
var dirsToTry = [ path.resolve(origDir, resolveTilde(sourceArg)) ];
// Find the first valid path in our list (valid paths contain a manifest.json file)
var foundManifest = false;
for (var i = 0; i < dirsToTry.length; i++) {
srcAppDir = dirsToTry[i];
console.log('Searching for Chrome app source in ' + srcAppDir);
if (fs.existsSync(path.join(srcAppDir, 'manifest.json'))) {
foundManifest = true;
break;
}
}
if (!srcAppDir) {
return Q.reject('Directory does not exist.');
}
if (!foundManifest) {
return Q.reject('No manifest.json file found');
}
}
})
.then(function() {
return require('./get-manifest')(srcAppDir);
})
.then(function(manifestData) {
if (!(manifestData.app && manifestData.app.background && manifestData.app.background.scripts && manifestData.app.background.scripts.length)) {
return Q.reject('No background scripts found in your manifest.json file. Your manifest must contain at least one script in the "app.background.scripts" array.');
}
manifest = manifestData;
})
.then(function() {
// Create step.
console.log('## Creating Your Application');
var config_default = JSON.parse(JSON.stringify(require('./default-config')(ccaRoot)));
config_default.lib.www = { uri: srcAppDir };
config_default.lib.www.link = !!flags['link-to'];
return require('./cordova-commands').runCmd(['create', destAppDir, packageId, appName, config_default]);
})
.then(function() {
process.chdir(destAppDir);
})
.then(function() {
if (!appWasImported) {
// Update app name if the app is not imported.
return Q.ninvoke(fs, 'readFile', manifestDesktopFilename, { encoding: 'utf-8' }).then(function(manifestDesktopData) {
var manifestDesktop;
try {
// jshint evil:true
manifestDesktop = eval('(' + manifestDesktopData + ')');
// jshint evil:false
} catch (e) {
console.error(e);
return Q.reject('Unable to parse manifest ' + manifestDesktopFilename);
}
manifestDesktop.name = appName || path.basename(destAppDir);
manifest.name = manifestDesktop.name;
Q.ninvoke(fs, 'writeFile', manifestDesktopFilename, JSON.stringify(manifestDesktop, null, 4));
});
}
})
.then(function() {
// Ensure the mobile manifest exists.
if (fs.existsSync(manifestMobileFilename)) return;
var defaultManifestMobileFilename = path.join(ccaRoot, 'templates', 'default-app', 'manifest.mobile.json');
if (!fs.existsSync(defaultManifestMobileFilename)) return; // TODO: Was I supposed to be an error?
shelljs.cp('-f', defaultManifestMobileFilename, manifestMobileFilename);
})
.then(function() {
// Update default packageId if needed.
return Q.ninvoke(fs, 'readFile', manifestMobileFilename, { encoding: 'utf-8' }).then(function(manifestMobileData) {
var newPackageId = packageId || ('com.your.company.' + (appName || manifest['name'].replace(/[^a-zA-Z0-9_]/g, '')));
// Replace rather than parse so as to maintain comments
manifestMobileData = manifestMobileData.replace('com.your.company.HelloWorld', newPackageId);
return Q.ninvoke(fs, 'writeFile', manifestMobileFilename, manifestMobileData);
});
})
.then(function() {
// If there is no config.xml, or the config.xml is the cordova default, replace it with our default
if (!appWasImported || !fs.existsSync(path.join('config.xml'))) {
console.log("## Creating default config.xml");
shelljs.cp('-f', path.join(ccaRoot, 'templates', 'config.xml'), path.join('config.xml'));
}
})
.then(function() {
return require('./get-manifest')('www');
})
.then(function(manifestJson) {
var configXmlData = fs.readFileSync('config.xml', 'utf8');
var analyzedManifest = ccaManifestLogic.analyseManifest(manifestJson);
var configXmlDom = new xmldom.DOMParser().parseFromString(configXmlData);
ccaManifestLogic.updateConfigXml(manifestJson, analyzedManifest, configXmlDom);
configXmlData = new xmldom.XMLSerializer().serializeToString(configXmlDom);
fs.writeFileSync('config.xml', configXmlData);
return require('./write-out-cca-version')();
})
.then(function() {
// Create scripts that update the cordova app on prepare
fs.mkdirSync(path.join('hooks', 'before_prepare'));
fs.mkdirSync(path.join('hooks', 'before_platform_add'));
function writeHook(path) {
var contents = [
"#!/usr/bin/env node",
"var cmdline = process.env['CORDOVA_CMDLINE'];",
"if (!/cca/.test(cmdline)) {",
" var msg = 'ERROR: This is a CCA based project! Using `cordova` rather than `cca` will have unexpected results.' ;",
" console.error(msg);",
" process.exit(1);",
"}"
];
fs.writeFileSync(path, contents.join('\n'));
fs.chmodSync(path, '777');
}
writeHook(path.join('hooks', 'before_prepare', 'cca-check.js'));
writeHook(path.join('hooks', 'before_platform_add', 'cca-check.js'));
})
.then(function() {
// Create a convenience gitignore
shelljs.cp('-f', path.join(ccaRoot, 'templates', 'DEFAULT_GITIGNORE'), path.join('.', '.gitignore'));
// Add default platforms:
var cmds = [];
if (flags.ios) {
cmds.push(['platform', 'add', 'ios']);
}
if (flags.android) {
cmds.push(['platform', 'add', 'android']);
}
return require('./cordova-commands').runAllCmds(cmds);
})
.then(function() {
var wwwPath = path.join(destAppDir, 'www');
var welcomeText = 'Done!\n\n';
if (flags['link-to']) {
welcomeText += 'Your project has been created, with web assets symlinked to the following chrome app:\n' +
wwwPath + ' --> ' + srcAppDir + '\n\n';
} else if (flags['copy-from']) {
welcomeText += 'Your project has been created, with web assets copied from the following chrome app:\n'+
srcAppDir + ' --> ' + wwwPath + '\n\n';
} else {
welcomeText += 'Your project has been created, with web assets in the `www` directory:\n'+
wwwPath + '\n\n';
}
welcomeText += 'Remember to run `cca prepare` after making changes if you are using an IDE.\n';
welcomeText += 'Full instructions: https://github.com/MobileChromeApps/mobile-chrome-apps/blob/master/docs/Develop.md#making-changes-to-your-app-source-code';
console.log(welcomeText);
});
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 1 1 1 | var path = require('path');
var fs = require('fs');
module.exports = exports = function defaultConfig(ccaRoot) {
var plugin_search_path = [
path.join(ccaRoot, 'cordova'),
];
// For plugin development with local cca git checkout.
var chrome_cordova_plugins = path.join(ccaRoot, '..', 'mobile-chrome-apps-plugins');
if (fs.existsSync(chrome_cordova_plugins)) {
plugin_search_path.push(chrome_cordova_plugins);
}
return {
plugin_search_path: plugin_search_path,
lib: {
android: {
// TODO: Remove uri here and below after cordova-lib@0.21.7 is released.
uri: path.join(ccaRoot, 'cordova', 'cordova-android'),
url: path.join(ccaRoot, 'cordova', 'cordova-android')
},
ios: {
uri: path.join(ccaRoot, 'cordova', 'cordova-ios'),
url: path.join(ccaRoot, 'cordova', 'cordova-ios')
}
}
};
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var childProcess = require('child_process');
var path = require('path');
function resolveTilde(string) {
if (string.substr(0,1) === '~')
return path.resolve(process.env.HOME + string.substr(1));
return string;
}
// Returns a promise
module.exports = exports = function exec(argv) {
argv = argv.map(resolveTilde);
var cmd = argv[0];
argv = argv.slice(1);
var child = childProcess.spawn(cmd, argv, { stdio: [0,1,2] });
child.on('close', process.exit);
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var fs = require('fs');
var path = require('path');
var Q = require('q');
var ccaManifestLogic = require('cca-manifest-logic');
// Returns a promise for the manifest contents.
module.exports = exports = function getManifest(manifestDir, platform) {
var manifestFilename = path.join(manifestDir, 'manifest.json');
function readFileFunc(p) {
return Q.ninvoke(fs, 'readFile', p, 'utf8');
}
return ccaManifestLogic.parseAndMergeManifests(manifestFilename, platform, readFileFunc, Q);
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 1 1 1 1 1 1 1 1 1 1 1 1 | var cordova = require('cordova');
var prePrepare = require('./pre-prepare');
var postPrepare = require('./post-prepare');
var beforePluginAdd = require('./before-plugin-add');
var cordovaLib = cordova.cordova_lib;
function registerHooks() {
cordovaLib.events.on('before_prepare', prePrepare);
cordovaLib.events.on('after_prepare', postPrepare);
cordovaLib.events.on('before_plugin_add', beforePluginAdd);
}
function unregisterHooks() {
cordovaLib.events.removeListener('before_prepare', prePrepare);
cordovaLib.events.removeListener('after_prepare', postPrepare);
cordovaLib.events.removeListener('before_plugin_add', beforePluginAdd);
}
exports.registerHooks = registerHooks;
exports.unregisterHooks = unregisterHooks;
exports.prePrepare = prePrepare;
exports.postPrepare = postPrepare;
exports.beforePluginAdd = beforePluginAdd;
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var optimist = require('optimist');
var path = require('path');
module.exports = exports = function parseCommandLine() {
var pathToApp = '<' + path.join('path', 'to', 'app') + '>';
return optimist
.usage('Usage: $0 <command> [commandArgs]\n' +
'\n' +
'checkenv - Ensures that your environment is setup correctly.\n' +
' Example:\n' +
' cca checkenv\n' +
'\n' +
'create <directory> [<id> [<name>]] [--android] [--ios] [--copy-from=' + pathToApp + ' | --link-to=' + pathToApp + '] - Creates a project.\n' +
' Details:\n' +
' <directory>: The directory to create the project in.\n' +
' <id>: The reverse domain-style identifier.\n' +
' <name>: The application\'s display text.\n' +
' --android: Add the Android platform (default if android SDK is detected).\n' +
' --ios: Add the iOS platform (default if Xcode is detected).\n' +
' --copy-from=' + pathToApp + ': Create a project based on the given Chrome App.\n' +
' --link-to=' + pathToApp + ': Create a project that symlinks to the given Chrome App.\n' +
'\n' +
'platform [{add|remove|rm} <PLATFORM>] ..... add or remove a specified PLATFORM, OR\n' +
' [{list|ls}] ...................... list all installed and available platforms\n' +
' [{update|up} <PLATFORM>] ......... update the version of Cordova used for a specific\n' +
' PLATFORM; use after updating the CLI.\n' +
'\n' +
'plugin [{add|remove|rm} <PATH|URI>] ....... add or remove a plugin from the specified PATH or URI, OR\n' +
' [{ls|list}] ........................ list all currently installed plugins\n' +
' [search <keyword1 keyword2...>] .... search the plugin registry for plugins matching the keywords\n' +
'\n' +
'prepare [PLATFORM..] ...................... copies files for specified platforms, or all platforms,\n' +
' so that the project is ready to build in each SDK\n' +
'\n' +
'upgrade ................................... upgrades platforms and plugins of this project with the latest\n' +
' versions after doing an npm update of cca.\n' +
' Note: you will be automatically prompted to upgrade, but you can\n' +
' skip the auto upgrade by passing --skip-upgrade to any command.\n' +
'\n' +
'build [--debug|--release]\n' +
' [--webview=system|--webview=crosswalk]\n' +
' [--android-minSdkVersion=#]\n' +
' [android|ios]........................ builds for the given platform(s)\n' +
'\n' +
'run [build flags]\n' +
' [--device|--emulator|--target=FOO]\n' +
' [android|ios|chrome] .................. deploys app on specified platform devices / emulators\n' +
'\n' +
'exec CMD [args...] ........................ runs the given command with all SDK tools added to your PATH\n' +
'\n' +
'push [--target=IP_ADDRESS:PORT] [--watch] . Pushes the app to one or more Chrome App Developer Tool instances.\n' +
' --target defaults to localhost:2424; can be specified multiple times.\n' +
' --watch enables a file watcher that auto-pushes when files change.\n' +
'\n' +
'Examples:\n' +
' cca create MyApp\n' +
' cca create MyApp --link-to=' + pathToApp + '\n' +
' cca prepare\n' +
' cca run android --device\n' +
' cca run ios --emulator\n' +
' cca build android --release --webview=system --android-minSdkVersion=20\n' +
' cca plugin ls')
.options('h', {
type: 'boolean',
alias: 'help',
desc: 'Show usage message.'
})
.options('d', {
type: 'boolean',
alias: 'verbose',
desc: 'Enable verbose logging.'
})
.options('v', {
type: 'boolean',
alias: 'version',
desc: 'Show version.'
})
.options('y', {
type: 'boolean',
alias: 'skip-prompt',
desc: 'Answer "yes" to any "yes/no" prompts.'
})
.options('skip-upgrade', {
type: 'boolean',
desc: 'Don\'t upgrade platforms and plugins.',
})
.options('android', { type: 'boolean' })
.options('ios', { type: 'boolean' })
.options('pause_on_exit', { type: 'boolean' })
.options('copy-from', { type: 'string' })
.options('link-to', { type: 'string' })
.options('target', { type: 'string' })
.options('webview', { type: 'string' })
.options('android-minSdkVersion', { type: 'number' })
.options('watch', { type: 'boolean' })
.options('release', { type: 'boolean' })
.options('debug', { type: 'boolean' })
.options('emulator', { type: 'boolean' })
.options('device', { type: 'boolean' })
.argv;
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 1 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var fs = require('fs');
var path = require('path');
var ccaManifestLogic = require('cca-manifest-logic');
var et = require('elementtree');
var Q = require('q');
var utils = require('./utils');
// Returns a promise.
module.exports = exports = function postPrepareCommand(opts) {
var hasAndroid = fs.existsSync(path.join('platforms', 'android'));
var hasIos = fs.existsSync(path.join('platforms', 'ios'));
if (!fs.existsSync('platforms')) {
return Q.reject('No platforms directory found. Please run script from the root of your project.');
}
var p = Q();
if (hasAndroid) {
p = p.then(function() { return postPrepareInternal('android'); });
}
if (hasIos) {
p = p.then(function() { return postPrepareInternal('ios'); });
}
return p;
};
function injectCsp(htmlPath, cspTag) {
var html = fs.readFileSync(htmlPath, 'utf8');
html = html.replace(/<meta.*Content-Security.*>/, cspTag);
fs.writeFileSync(htmlPath, html);
}
// Internal function called potentially multiple times to cover all platforms.
function postPrepareInternal(platform) {
var root = utils.assetDirForPlatform(platform);
var localesPath = path.join(utils.assetDirForPlatform(platform), '_locales');
return Q().then(function() {
if (!fs.existsSync(localesPath)) {
return;
}
console.log('## Normalizing _locales for ' + platform);
return Q.ninvoke(fs, 'readdir', localesPath)
.then(function(files) {
files.forEach(function(f) {
var fullName = path.join(localesPath, f);
var adjustedFilename = f.replace('-', '_').toLowerCase();
if (f !== adjustedFilename) {
var stats = fs.statSync(fullName);
if (stats.isDirectory()) {
fs.renameSync(fullName, path.join(localesPath, adjustedFilename));
}
}
});
});
}).then(function() {
return require('./get-manifest')('www', platform);
}).then(function(manifest) {
// Write merged manifest.json
fs.writeFileSync(path.join(root, 'manifest.json'), JSON.stringify(manifest, null, 4));
// Write CSP tag
// - Check first if plugin is installed yet
var bootstrapPluginPath = path.join(root, 'plugins', 'cordova-plugin-chrome-apps-bootstrap');
if (fs.existsSync(bootstrapPluginPath)) {
console.log('## Inject CSP for ' + platform);
var cspContent = ccaManifestLogic.analyseManifest.createCspString(manifest, platform);
var cspTag = '<meta http-equiv="Content-Security-Policy" content="' + cspContent + '">';
injectCsp(path.join(bootstrapPluginPath, 'chromeapp.html'), cspTag);
injectCsp(path.join(bootstrapPluginPath, 'chromebgpage.html'), cspTag);
}
if (platform === 'android') {
// Write manifest.short_name as launcher_name in Android strings.xml
if (manifest.short_name) {
var stringsPath = path.join('platforms', 'android', 'res', 'values', 'strings.xml');
var strings = et.parse(fs.readFileSync(stringsPath, 'utf-8'));
strings.find('./string/[@name="launcher_name"]').text = manifest.short_name;
fs.writeFileSync(stringsPath, strings.write({indent: 4}), 'utf-8');
}
}
});
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | 1 1 1 1 1 1 1 1 1 1 1 | /**
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
'use strict';
var fs = require('fs');
var et = require('elementtree');
var xmldom = require('xmldom');
var path = require('path');
// Use double underscore because the Node REPL uses "_" to hold the result of the last operation.
var __ = require('underscore');
var utils = require('./utils');
var ccaManifestLogic = require('cca-manifest-logic');
var cordova = require('cordova');
var cordovaLib = cordova.cordova_lib;
// Returns a promise.
module.exports = exports = function prePrepareCommand(context) {
// context is the Context object passed in by cordova-lib/HooksRunner.
var pluginsToBeInstalled = [];
var pluginsToBeNotInstalled = [];
var pluginsNotRecognized = [];
var manifest, whitelist;
// Convert all plugin IDs to lower case (registry has problems with upper case).
var installedPlugins = context.cordova.plugins.map(function(s) { return s.toLowerCase(); });
var argv = require('optimist')
.options('webview', { type: 'string' })
.options('release', { type: 'boolean' })
.options('link', { type: 'boolean' })
.options('verbose', { type: 'boolean', alias: 'd' })
.argv;
// Pre-prepare manifest check and project munger
return require('./get-manifest')('www')
.then(function(m) {
manifest = m;
if (argv.webview) {
manifest.webview = argv.webview;
}
return ccaManifestLogic.analyseManifest(manifest);
})
.then(function(manifestData) {
pluginsToBeInstalled = manifestData.pluginsToBeInstalled.concat(['org.chromium.cca-hooks']);
pluginsToBeNotInstalled = manifestData.pluginsToBeNotInstalled.concat();
pluginsNotRecognized = manifestData.pluginsNotRecognized;
whitelist = manifestData.whitelist;
var configXmlData = fs.readFileSync('config.xml', 'utf8');
var configXmlDom = new xmldom.DOMParser().parseFromString(configXmlData);
ccaManifestLogic.updateConfigXml(manifest, manifestData, configXmlDom);
var newConfigData = new xmldom.XMLSerializer().serializeToString(configXmlDom);
// Don't write out if nothing actually changed
if (newConfigData != configXmlData) {
console.log('## Updating config.xml from manifest.json');
fs.writeFileSync('config.xml', newConfigData);
}
})
.then(function() {
if ( (context.cordova.platforms.indexOf('android') != -1) && argv['release']) {
if (!fs.existsSync('android-release-keys.properties')) {
utils.fatal('Cannot build android in release mode: android-release-keys.properties not found in project root.');
}
}
// Add a URL type to the iOS project's .plist file.
// This is necessary for chrome.identity to redirect back to the app after authentication.
var hasIos = fs.existsSync(path.join('platforms', 'ios'));
if (hasIos) {
var platforms = cordovaLib.cordova_platforms;
var parser = platforms.getPlatformApi('ios');
var infoPlistPath = path.join('platforms', 'ios', parser._parser.originalName, parser._parser.originalName + '-Info.plist');
var infoPlistXml = et.parse(fs.readFileSync(infoPlistPath, 'utf-8'));
var rootPlistElement = infoPlistXml.getroot();
var rootDictElement = rootPlistElement.getItem(0);
var bundleUrlTypesKey = et.SubElement(rootDictElement, 'key');
bundleUrlTypesKey.text = 'CFBundleURLTypes';
var bundleUrlTypesArray = et.SubElement(rootDictElement, 'array');
var bundleUrlTypesDict = et.SubElement(bundleUrlTypesArray, 'dict');
var bundleTypeRoleKey = et.SubElement(bundleUrlTypesDict, 'key');
bundleTypeRoleKey.text = 'CFBundleTypeRole';
var bundleTypeRoleString = et.SubElement(bundleUrlTypesDict, 'string');
bundleTypeRoleString.text = 'Editor';
var bundleUrlNameKey = et.SubElement(bundleUrlTypesDict, 'key');
bundleUrlNameKey.text = 'CFBundleURLName';
var bundleUrlNameString = et.SubElement(bundleUrlTypesDict, 'string');
bundleUrlNameString.text = manifest.packageId;
var bundleUrlSchemesKey = et.SubElement(bundleUrlTypesDict, 'key');
bundleUrlSchemesKey.text = 'CFBundleURLSchemes';
var bundleUrlSchemesArray = et.SubElement(bundleUrlTypesDict, 'array');
var bundleUrlSchemeString = et.SubElement(bundleUrlSchemesArray, 'string');
bundleUrlSchemeString.text = manifest.packageId;
fs.writeFileSync(infoPlistPath, infoPlistXml.write({indent: 4}), 'utf-8');
}
})
.then(function() {
var missingPlugins = __.difference(pluginsToBeInstalled, installedPlugins);
var excessPlugins = __.intersection(installedPlugins, pluginsToBeNotInstalled);
function pinVersion(pluginId, version) {
var idx = missingPlugins.indexOf(pluginId);
if (idx != -1) {
missingPlugins[idx] += '@' + version;
}
}
if (missingPlugins.length || excessPlugins.length || pluginsNotRecognized.length) {
console.log('## Updating plugins based on manifest.json');
pluginsNotRecognized.forEach(function(unknownPermission) {
console.warn('Permission not recognized by cca: ' + unknownPermission + ' (ignoring)');
});
var opts = {
link: argv.link,
verbose: argv.verbose
};
var cmds = [];
if (missingPlugins.length) {
// Pin major versions of plugins that we care about
pinVersion('cordova-plugin-chrome-apps-navigation', '1');
pinVersion('cordova-plugin-chrome-apps-i18n', '2');
pinVersion('cordova-plugin-chrome-apps-bootstrap', '3');
pinVersion('cordova-plugin-crosswalk-webview', '1');
cmds.push(['plugin', 'add', missingPlugins, opts]);
}
if (excessPlugins.length) {
cmds.push(['plugin', 'rm', excessPlugins, opts]);
}
return require('./cordova-commands').runAllCmds(cmds);
}
})
.then(function() {
// After adding/removing plugins above, the list of installed plugins is:
installedPlugins = __.difference(__.union(installedPlugins, pluginsToBeInstalled), pluginsToBeNotInstalled);
// If chrome.identity is installed, we need a client id.
if (installedPlugins.indexOf('cordova-plugin-chrome-apps-identity') >= 0) {
if (!manifest.oauth2 || !manifest.oauth2.client_id) {
console.warn('Warning: chrome.identity requires a client ID to be specified in the manifest.');
}
}
});
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | var fs = require('fs');
var path = require('path');
var Q = require('q');
var debounce = require('debounce');
var utils = require('./utils');
var child_process = require('child_process');
// Returns a promise.
module.exports = exports = function push(target, watch) {
var argsAsJson = JSON.stringify([].slice.call(arguments));
return checkFileHandleLimit()
.then(function(fileHandleLimit) {
if (fileHandleLimit < 10000 && watch) {
return relaunchWithBiggerUlimit(argsAsJson)
.then(function() {
return true;
}, function() {
// Setting ulimit can fail, so just continue on if it does.
});
}
}).then(function(done) {
if (done) {
return;
}
target = !target || Array.isArray(target) ? target : [target];
var ret = Q.when(target);
if (!target) {
ret = extractTargets();
}
return ret.then(function(targets) {
return createSession(targets);
}).then(function(session) {
// Push the app and force a launch, even if it hasn't changed from a previous launch, since the app is being pushed for the first time.
return pushAll(session.clientInfos, /* forceLaunch */ true)
.then(function() {
if (watch) {
return watchFiles(session);
}
});
});
});
};
function extractTargets() {
// TODO: Use adbkit for smarter auto-detection.
var PushClient = require('chrome-app-developer-tool-client');
return PushClient.detectAdbTargets()
.then(function(targets) {
if (!targets.length) {
console.warn('No connected android devices detected. Defaulting to localhost.');
targets = ['localhost:2424'];
}
return targets;
}, function() {
console.warn('Could not use adb to detect connected devices');
return ['localhost:2424'];
});
}
function createSession(targets) {
var PushClient = require('chrome-app-developer-tool-client');
var i = 0;
var ret = {
platforms: [],
clientInfos: [],
appType: null
};
var chromeAppPushRoot = null;
if (fs.existsSync('www/manifest.json')) {
chromeAppPushRoot = 'www';
} else if (fs.existsSync('manifest.json')) {
chromeAppPushRoot = '.';
}
ret.appType = chromeAppPushRoot ? 'chrome' : 'cordova';
var platformMap = Object.create(null);
function createClient() {
var target = targets[i++];
if (!target) {
ret.platforms = Object.keys(platformMap);
return ret;
}
var newClient = new PushClient(target);
return newClient.info()
.then(function(response) {
var infoJson = response.body;
var platform = infoJson['platform'];
platformMap[platform] = true;
if (ret.appType == 'chrome') {
ret.clientInfos.push({
platform: platform,
client: newClient,
pushSession: newClient.createPushSession(chromeAppPushRoot),
watchDir: chromeAppPushRoot
});
} else {
// Vanilla Cordova project.
var wwwDir = utils.assetDirForPlatform(platform);
ret.clientInfos.push({
platform: platform,
client: newClient,
pushSession: newClient.createPushSession('.'), // push client figures out to use platforms/
watchDir: wwwDir
});
}
return createClient();
}, function(error) {
if (error.code === 'ECONNREFUSED') {
console.warn();
console.warn('Could not connect to device at ' + target);
console.warn('For a USB connected Android device, try running: adb forward tcp:2424 tcp:2424');
console.warn('For a networked device, use --target=DEVICE_IP_ADDRESS');
} else if (error.code === 'ECONNRESET') {
console.warn('\nPlease make sure that the Chrome App Developer Tool for Mobile is running on your device.');
} else {
console.error(error);
}
process.exit();
});
}
return createClient();
}
var pushInProgress = false;
var pushAgainWhenDone = false;
// gaze uses fs.watchFile, which is classified as "unstable" (http://goo.gl/H16j5l).
// It sometimes causes multiple change events to be fired, and they're far enough apart that debouncing is ineffective.
// To deal with this, CADT-client's push functionality doesn't relaunch an app with no changes unless `forceLaunch` is true.
// Calls to `pushAll` can specify whether to force a launch.
function pushAll(clientInfos, forceLaunch) {
if (pushInProgress) {
pushAgainWhenDone = true;
return Q();
}
pushInProgress = true;
var allPromises = clientInfos.map(function(clientInfo) {
try {
return clientInfo.pushSession.push(forceLaunch);
} catch (e) {
if (/Not a Cordova project/.test(e)) {
console.warn('Please navigate to a Chrome App or Cordova project, and then try pushing again.');
} else {
console.error(e);
}
process.exit();
}
});
return Q.all(allPromises)
.then(function() {
if (pushAgainWhenDone) {
process.nextTick(function() {
// Push, but don't force a launch if the app hasn't changed.
pushAll(clientInfos, /* forceLaunch */ false).done();
});
}
pushInProgress = false;
pushAgainWhenDone = false;
}, function(e) {
pushInProgress = false;
pushAgainWhenDone = false;
throw e;
});
}
var debouncedPushAll = debounce(function(clientInfos) {
// Push, but don't force a launch if the app hasn't changed.
pushAll(clientInfos, /* forceLaunch */ false).done();
}, 50, false);
function watchFiles(session) {
var gaze = require('gaze');
var deferred = Q.defer();
// TODO: This doesn't work for vanilla cordova apps + multiple platforms.
var watchDir = session.clientInfos[0].watchDir;
// Note: gaze doesn't work well with ./ prefix nor with absolute paths
// (https://github.com/gruntjs/grunt-contrib-watch/issues/166)
// path.join() is smart enough to remove the ./ prefix.
gaze(path.join(watchDir, '**', '*'), function(err, watcher) {
console.log('Watching for changes.');
watcher.on('all', function(event, filepath) {
debouncedPushAll(session.clientInfos);
});
});
// TODO: Capture Ctrl-C and resolve the promise.
return deferred.promise;
}
function checkFileHandleLimit() {
var deferred = Q.defer();
if (process.platform != 'win32' && process.env['SHELL']) {
// gaze opens a lot of file handles, and the default on OS X is too small (EMFILE exceptions).
// NOTE: This is fixed in node 0.11, and is a problem only on node 0.10.
child_process.exec('ulimit -n', function(error, stdout, stderr) {
var curLimit = !error && +stdout;
deferred.resolve(curLimit || Infinity);
});
} else {
deferred.resolve(Infinity);
}
return deferred.promise;
}
function relaunchWithBiggerUlimit(argsAsJson) {
// re-run with the new ulimit
var deferred = Q.defer();
var args = ['-c', 'ulimit -n 10240 && exec "' + process.argv[0] + '" "' + __filename + '" "' + argsAsJson.replace(/"/g, '@') + '"'];
var child = child_process.spawn('sh', args, { stdio: 'inherit' });
child.on('close', function(code) {
if (code) {
deferred.reject(code);
} else {
deferred.resolve(code);
}
});
return deferred.promise;
}
// Gets called from EMFILE re-launch
Iif (require.main === module) {
exports.apply(this, JSON.parse(process.argv[2].replace(/@/g, '"'))).done();
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 1 1 1 1 1 | var fs = require('fs');
var path = require('path');
var Q = require('q');
var child_process = require('child_process');
// Returns a promise.
module.exports = exports = function runInChrome(platform) {
var chromeAppRunRoot = null;
if (fs.existsSync('www/manifest.json')) {
chromeAppRunRoot = 'www';
} else if (fs.existsSync('manifest.json')) {
chromeAppRunRoot = '.';
} else {
return Q.reject('Not a chrome app.');
}
var chromeArgs = ['--load-and-launch-app=' + path.resolve(chromeAppRunRoot)]; // '--disable-web-security'
if (platform === 'canary') {
chromeArgs.push('--user-data-dir=/tmp/cca_chrome_data_dir');
}
return Q.fcall(function() {
var chromeExe = null;
if (process.platform === 'win32') {
chromeExe = 'Chrome' + (platform === 'canary' ? ' Canary' : '');
child_process.spawn('cmd', ['/s', '/c', 'start', chromeExe].concat(chromeArgs));
} else if (process.platform === 'darwin') {
chromeExe = 'Google Chrome' + (platform === 'canary' ? ' Canary' : '');
child_process.spawn('open', ['-n', '-a', chromeExe, '--args'].concat(chromeArgs));
}
});
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 1 1 1 1 1 1 1 1 1 | var Q = require('q');
var utils = require('./utils');
var check_reqs = require('../cordova/cordova-android/bin/lib/check_reqs');
var hasAndroidPlatform;
var hasXcode;
function checkHasAndroid() {
hasAndroidPlatform = false;
return check_reqs.check_java()
.then(function() {
return check_reqs.check_android()
.then(function() {
console.warn('\x1B[32mAndroid Development: SDK configured properly.\x1B[39m');
hasAndroidPlatform = true;
}, function(err) {
console.warn('Android Development: ' + err.message);
});
}, function(err) {
console.warn('Android Development: JDK not found. ' + err.message);
return Q.reject();
}).then(null, function(){});
}
function checkHasIos() {
if (process.platform != 'darwin')
return Q();
return utils.exec('which xcodebuild', true /* opt_silent */)
.then(function() {
return utils.exec('xcodebuild -version', true /* opt_silent */)
.then(function() {
hasXcode = true;
console.warn('\x1B[32miOS Development: SDK configured properly.\x1B[39m');
}, function(err) {
console.warn('iOS Development: Xcode appears to be installed, but no version is selected (fix this with xcodeselect).');
});
}, function(err) {
console.warn('iOS Development: SDK not detected.');
});
}
// Returns a promise.
module.exports = exports = function toolsCheck() {
var ret = Q();
// Is this the first time we're checking for the tools?
if (typeof hasAndroidPlatform == 'undefined') {
ret = ret.then(function() {
return checkHasAndroid().then(checkHasIos);
});
}
return ret.then(function() {
if (!hasAndroidPlatform && !hasXcode)
// TODO: Replace inline docs links with general instructions to read --help / docs / report issues
return Q.reject('No usable build environment could be found. Please refer to our installation guide:\n' +
'https://github.com/MobileChromeApps/mobile-chrome-apps/blob/master/docs/Installation.md');
return Q({
hasAndroidPlatform: hasAndroidPlatform,
hasXcode: hasXcode,
});
});
};
exports.fixEnv = function() {
return check_reqs.check_java()
.then(function() {
return check_reqs.check_android();
})
.then(null, function() {});
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | var fs = require('fs');
var Q = require('q');
var path = require('path');
var shelljs = require('shelljs');
var __ = require('underscore');
var utils = require('./utils');
var cordova = require('cordova');
var hooks = require('./hooks');
// Exports
exports.upgradeProject = upgradeProject;
exports.upgradeProjectIfStale = upgradeProjectIfStale;
// The list of platforms we currently have installed
function getInstalledPlatfroms() {
return ['ios', 'android'].filter(function(p){
return fs.existsSync(path.join('platforms', p));
});
}
// Get the list of supported platforms. Returns a promise.
function getSupportedPlatforms() {
var plats = [];
return require('./tools-check')()
.then(function(toolsCheckResults) {
if (toolsCheckResults.hasAndroidPlatform) {
plats.push('android');
}
if (toolsCheckResults.hasXcode ) {
plats.push('ios');
}
return plats;
});
}
// Get the list of all plugins managed by CCA
function getCcaPlugins() {
var pluginMaps = require('cca-manifest-logic').pluginMaps;
// The list of plugins is constructed from all plugin IDs in:
// pluginMaps.DEFAULT_PLUGINS (Array)
// pluginMaps.*_MAP (objects)
var ccaPlugins = __.map(pluginMaps, function(val, key) {
return /_MAP/.test(key) ? __.values(val) : [];
});
ccaPlugins.push(pluginMaps.DEFAULT_PLUGINS);
ccaPlugins = __.uniq(__.flatten(ccaPlugins));
return ccaPlugins;
}
// This function is run on almost any cca invocation
// It will run "upgrade" if either:
// 1. The project has not platforms installed
// 2. The file ./platforms/created-with-cca-version contains older version string
// 3. The file ./platforms/created-with-cca-version does not exist
function upgradeProjectIfStale(skipPrompt) {
var packageVersion = require('../package').version;
var installedPlatfroms = getInstalledPlatfroms();
if (!installedPlatfroms.length) {
// No platforms installed yet, (ab)use upgradeProject(skipPrompt=true) to install both.
// Ideally we would do this in pre-prepare, but cordova doesn't run pre-prepare scripts if there
// are no target platforms, and its unclear how to make it do so with a difference concept
// for pre-prepare scripts.
return exports.upgradeProject(true);
} else {
var versionFile = path.join('platforms', 'created-with-cca-version');
var createdWith;
if (fs.existsSync(versionFile)) {
createdWith = fs.readFileSync(versionFile, 'utf-8').trim();
}
if (createdWith == packageVersion) {
return Q();
} else {
// The platforms/created-with-cca-version file does not exist or contains older version string. Upgrading.
console.log('This project was not upgraded to cca v' + packageVersion + ' yet. Attempting to upgrade now...');
return exports.upgradeProject(skipPrompt);
}
}
}
function upgradeProject(skipPrompt) {
var argv = require('optimist')
.options('link', { type: 'boolean' })
.options('verbose', { type: 'boolean', alias: 'd' })
.argv;
var hadPlatforms = [];
return Q()
.then(function(){
if (skipPrompt) return 'y';
return utils.waitForKey('Warning: Upgrade will replace all files in platforms and plugins. Continue? [y/N] ');
})
.then(function(key) {
if (key != 'y' && key != 'Y') {
return Q.reject('Okay, nevermind.');
}
})
.then(function() {
// Upgrading!
// We don't want the pre/post prepare hooks to fire during upgrade.
hooks.unregisterHooks();
// Remove the old file based pre/post prepare hooks
// TODO: Remove this later. Last version to use file based hooks was 4.0.0 released in Oct 2014.
shelljs.rm('-f', path.join('hooks', 'before_prepare', 'cca-pre-prepare.js'));
shelljs.rm('-f', path.join('hooks', 'after_prepare', 'cca-post-prepare.js'));
// Remember what platforms we had before deleting them. If we only had one, don't install the other after upgrade.
hadPlatforms = getInstalledPlatfroms();
shelljs.rm('-rf', 'platforms');
shelljs.rm('-f', path.join('plugins', 'android.json'));
shelljs.rm('-f', path.join('plugins', 'ios.json'));
var installedPlugins = cordova.cordova_lib.PluginInfo.loadPluginsDir('plugins');
installedPlugins = __.pluck(installedPlugins, 'id');
// Only remove the CCA managed plugins
var allCcaPlugins = getCcaPlugins();
var pluginsToRemove = __.intersection(allCcaPlugins, installedPlugins);
if (pluginsToRemove && pluginsToRemove.length) {
return require('./cordova-commands').runCmd(['plugin', 'rm', pluginsToRemove]);
}
})
.then(function() {
console.log('## First-time build. Detecting available SDKs:');
return getSupportedPlatforms();
})
.then(function(plats) {
if (plats.length) {
// If this is a real upgrade, only install the platforms we had before.
if (hadPlatforms.length) {
plats = __.intersection(plats, hadPlatforms);
}
var opts = {
link: argv.link,
verbose: argv.verbose
};
return require('./cordova-commands').runCmd(['platform', 'add', plats, opts]);
}
})
.then(function() {
// Turn the hooks back on and fire prepare. The pre-prepare hook is what
// installs all the cca plugins back.
hooks.registerHooks();
return cordova.raw.prepare();
})
.then(require('./write-out-cca-version'));
}
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 1 1 1 1 1 1 1 1 1 1 1 1 | var Q = require('q');
var path = require('path');
var childProcess = require('child_process');
exports.exit = function exit(code) {
if (exports.exit.pause_on_exit) {
exports.waitForKey(function() {
process.exit(code);
});
} else {
process.exit(code);
}
};
exports.exit.pause_on_exit = false;
exports.fatal = function fatal(msg) {
console.error(msg);
if (msg && msg.stack) console.error(msg.stack);
exports.exit(1);
};
exports.fixPathSlashes = function fixPathSlashes(p) {
return exports.isWindows() ? p.replace(/\//g, '\\') : p;
};
exports.colorizeConsole = function colorizeConsole() {
var origWarn = console.warn;
console.warn = function() {
var msg = [].slice.call(arguments).join(' ');
origWarn.call(console, '\x1B[33m' + msg + '\x1B[39m');
};
console.error = function() {
var msg = [].slice.call(arguments).join(' ');
origWarn.call(console, '\x1B[31m' + msg + '\x1B[39m');
};
};
exports.assetDirForPlatform = function assetDirForPlatform(platform) {
if (platform === 'android') {
return path.join('platforms', platform, 'assets','www');
}
return path.join('platforms', platform, 'www');
};
// Returns a promise for an object with 'stdout' and 'stderr' as keys.
exports.exec = function exec(cmd, opt_silent) {
if (!opt_silent) {
console.log('Running: ' + cmd);
}
var d = Q.defer();
childProcess.exec(cmd, function(error, stdout, stderr) {
if (error) {
d.reject(error);
} else {
d.resolve({
stdout: stdout.trim(),
stderr: stderr.trim()
});
}
});
return d.promise;
};
// Returns a promise with the key as its value.
exports.waitForKey = function waitForKey(opt_prompt) {
opt_prompt = opt_prompt || 'Press the Any Key';
process.stdout.write(opt_prompt);
process.stdin.resume();
try {
// This fails if the process is a spawned child (likely a node bug);
process.stdin.setRawMode(true);
} catch (e) {
}
process.stdin.setEncoding('utf8');
var d = Q.defer();
process.stdin.on('data', function cont(key) {
if (key == '\u0003') {
process.exit(2);
}
process.stdin.removeListener('data', cont);
process.stdin.pause();
process.stdout.write('\n');
d.resolve(key);
});
return d.promise;
};
exports.isWindows = function isWindows() {
return process.platform.slice(0, 3) == 'win';
};
|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | 1 1 1 1 | var fs = require('fs');
var path = require('path');
var Q = require('q');
module.exports = exports = function writeOutCcaVersion() {
var packageVersion = require('../package').version;
if (!fs.existsSync(path.join('platforms'))) {
return Q.reject('Must have a platforms/ directory to write out the cca version used to add them.');
}
return Q.ninvoke(fs, 'writeFile', path.join('platforms', 'created-with-cca-version'), packageVersion, { encoding: 'utf-8' });
};
|